package com.xbongbong.paas.service.workflow.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.formula.constant.Constant;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.constant.WorkflowConstant;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasFormSubDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTaskEntity;
import com.xbongbong.paas.domain.entity.ext.FieldPermissionEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasAttachmentEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.ProcessSearchStatusTodoEnum;
import com.xbongbong.paas.enums.ProcessTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.feign.WorkOrderV2WorkflowFeignClient;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.UserInfoHelp;
import com.xbongbong.paas.help.WorkflowHelp;
import com.xbongbong.paas.help.WorkflowNodeHelp;
import com.xbongbong.paas.help.WorkflowOperateHelp;
import com.xbongbong.paas.help.WorkflowRecordLogHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.ApprovalLogPOJO;
import com.xbongbong.paas.pojo.ProcessNodeTaskLogPoJo;
import com.xbongbong.paas.pojo.ProcessNodeTaskOperatePojo;
import com.xbongbong.paas.pojo.ProcessNodeTaskPojo;
import com.xbongbong.paas.pojo.ProcessNodeTaskRecordsPojo;
import com.xbongbong.paas.pojo.dto.FormDataDeleteBatchDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.ProcessTaskDelDTO;
import com.xbongbong.paas.pojo.dto.SummaryDataDTO;
import com.xbongbong.paas.pojo.dto.UserGetDTO;
import com.xbongbong.paas.pojo.vo.FormDataDeleteBatchVO;
import com.xbongbong.paas.pojo.vo.MobileModeGetVO;
import com.xbongbong.paas.pojo.vo.PaasProcessNodeTaskVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.ProcessNextNodeTaskGetVO;
import com.xbongbong.paas.pojo.vo.ProcessTemplateNodeVO;
import com.xbongbong.paas.pojo.vo.SummaryDataVO;
import com.xbongbong.paas.pojo.vo.UserGetVO;
import com.xbongbong.paas.pojo.workflow.WorkflowNodeTreePojo;
import com.xbongbong.paas.pojo.workflow.operate.dto.ViewWholeWorkflowDTO;
import com.xbongbong.paas.pojo.workflow.operate.vo.ViewWholeWorkflowVO;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowGetPojo;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowBatchPrintByProcessDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowCommentListDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowDetailForListDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowNodeAllReadDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowNodeCheckUpdateRecordDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowNodeItemDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowNodeTaskCountDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowNodeTaskGetDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowNodeTaskListDTO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowNodeTaskReadDTO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowBatchPrintByProcessVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowCommentListVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeCheckUpdateRecordVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeTaskCountVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeTaskGet4IndexVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeTaskGetVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeTaskListVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeTaskRecordsVO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeTaskShowVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.WorkflowOperatorDataService;
import com.xbongbong.paas.service.dingtalkTodo.WorkflowDingtalkTodoService;
import com.xbongbong.paas.service.workflow.WorkflowApproveListPageOperationService;
import com.xbongbong.paas.service.workflow.approveListPage.WorkflowApproveListPageService;
import com.xbongbong.paas.service.workflow.comment.WorkflowCommentService;
import com.xbongbong.paas.service.workflow.detail.WorkflowApproveDetailService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.pojo.PermissionTermsPojo;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.paas.util.WorkflowNodeUtil;
import com.xbongbong.paas.util.WorkflowValidateUtil;
import com.xbongbong.parent.parse.data.FormDataDetailAnalysisDataHelp;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ApprovalErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.help.UserConfigHelp;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.enums.BusinessCommentEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.SignTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PublicGroupSeniorModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.util.DepartmentFieldUtil;
import com.xbongbong.saas.util.UserFieldUtil;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowDataChangeRecordEntity;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowCommentEntityExt;
import com.xbongbong.workflow.domain.entity.ext.WorkflowNodeEntityExt;
import com.xbongbong.workflow.domain.entity.ext.WorkflowTaskNodeEntityExt;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.model.WorkflowDataChangeRecordModel;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.changerecord.ChangeRecordOtherFieldBasicPojo;
import com.xbongbong.workflow.pojo.changerecord.ChangeRecordSubFormColumnPojo;
import com.xbongbong.workflow.pojo.changerecord.ChangeRecordSubFormFieldBasicPojo;
import com.xbongbong.workflow.pojo.changerecord.ChangeRecordSubFormHeadPojo;
import com.xbongbong.workflow.pojo.changerecord.ChangeRecordSubFormMidPojo;
import com.xbongbong.workflow.pojo.changerecord.ValuePojo;
import com.xbongbong.workflow.pojo.nodes.ApprovalNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author chenpeng
 * @version 1.0
 * @date 2021-05-24 17:11
 * @description
 */
@Service
@Slf4j
public class WorkflowApproveListPageOperationServiceImpl implements WorkflowApproveListPageOperationService {

    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;
    @Resource
    private WorkflowDingtalkTodoService workflowDingtalkTodoService;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private WorkflowApproveListPageService workflowApproveListPageService;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private WorkflowCommentService workflowCommentService;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private UserInfoHelp userInfoHelp;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private WorkflowOperatorDataService workflowOperatorDataService;
    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private UserConfigHelp userConfigHelp;
    @Resource
    private WorkflowNodeHelp workflowNodeHelp;
    @Resource
    private WorkflowHelp workflowHelp;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private WorkflowOperateHelp workflowOperateHelp;
    @Resource
    private WorkflowApproveDetailService workflowApproveDetailService;
    @Resource
    private WorkOrderV2WorkflowFeignClient workOrderV2WorkflowFeignClient;
    @Resource
    private PublicGroupSeniorModel publicGroupSeniorModel;
    @Resource
    private WorkflowDataChangeRecordModel workflowDataChangeRecordModel;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private FormDataDetailAnalysisDataHelp formDataDetailAnalysisDataHelp;
    @Resource
    private WorkflowRecordLogHelp workflowRecordLogHelp;
    /**
     * 删除节点任务
     *
     * @param processTaskDelDTO
     * @return
     * @throws XbbException
     */
    @Override
    public BaseVO delTask(ProcessTaskDelDTO processTaskDelDTO) throws XbbException {
        String corpid = processTaskDelDTO.getCorpid();
        // 判断是否有删除流程的权限
        Set<String> permSet = processTaskDelDTO.getLoginUser().getPermSet();
        if (!permSet.contains(ProPermissionAliasEnum.PROCESS_DELETE.getAlias())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100050, String.format(SystemErrorCodeEnum.API_ERROR_100050.getMsg(), ProPermissionAliasEnum.PROCESS_DELETE.getMemo()));
        }
        WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(processTaskDelDTO.getTaskId(), corpid);
        if (workflowTaskEntity == null) {
            throw new XbbException(ApprovalErrorCodeEnum.API_ERROR_209002, ApprovalErrorCodeEnum.API_ERROR_209002.getMsg());
        }
        if (!Objects.equals(FlowStatusEnum.PASS.getType(), workflowTaskEntity.getFlowStatus()) && !Objects.equals(FlowStatusEnum.REJECT.getType(), workflowTaskEntity.getFlowStatus()) && !Objects.equals(FlowStatusEnum.REVOKE.getType(), workflowTaskEntity.getFlowStatus())) {
            throw new XbbException(ApprovalErrorCodeEnum.API_ERROR_209017, ApprovalErrorCodeEnum.API_ERROR_209017.getMsg());
        }
        // 老审批逻辑
        PaasFormEntity paasFormEntityExt = proFormHelp.getPaasForm(workflowTaskEntity.getFormId(), workflowTaskEntity.getBusinessType(), corpid);
        List<Integer> businessTypeList = Arrays.asList(XbbRefTypeEnum.INVOICE.getCode(), XbbRefTypeEnum.PAYMENT_SHEET.getCode(), XbbRefTypeEnum.CREDIT_TEMPORARY_LIMIT.getCode(), XbbRefTypeEnum.CREDIT_FIXED_LIMIT.getCode());
        if (Objects.nonNull(paasFormEntityExt) && Objects.equals(paasFormEntityExt.getDistributorMark(), 1) && businessTypeList.contains(paasFormEntityExt.getBusinessType())) {
            throw new XbbException(ApprovalErrorCodeEnum.API_ERROR_209016);
        }
        WorkflowTransferDataEntity workflowTransferDataEntity = workflowTransferDataModel.getByTaskId(workflowTaskEntity.getId(), corpid);
        WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(workflowTransferDataEntity.getData().toJSONString(), WorkflowTransferPOJO.class);
        try {
            if (Objects.equals(WorkflowOperateEnum.ADD.getType(), workflowTransferPOJO.getOperate())) {
                PaasFormDataEntity paasFormDataEntity =formDataHelp.getFormDataEntity(corpid, workflowTaskEntity.getSaasMark(), workflowTaskEntity.getBusinessType(), workflowTaskEntity.getDataId());
                if (Objects.equals(FlowStatusEnum.REJECT.getType(), paasFormDataEntity.getFlowStatus()) || Objects.equals(FlowStatusEnum.REVOKE.getType(), paasFormDataEntity.getFlowStatus())) {
                    // 审批拒绝、撤回的数据，可以删掉主数据
                    // 增加 i18n 参数
                    Locale locale = LocaleContextHolder.getLocale();
                    String lang = locale.toString();
                    FormDataDeleteBatchDTO formDataDeleteBatchDTO = new FormDataDeleteBatchDTO();
                    formDataDeleteBatchDTO.setDataIdList(Arrays.asList(workflowTaskEntity.getDataId()));
                    formDataDeleteBatchDTO.setCorpid(corpid);
                    formDataDeleteBatchDTO.setUserId(processTaskDelDTO.getUserId());
                    formDataDeleteBatchDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
                    formDataDeleteBatchDTO.setBusinessType(workflowTaskEntity.getBusinessType());
                    formDataDeleteBatchDTO.setFormId(workflowTaskEntity.getFormId());
                    formDataDeleteBatchDTO.setAppId(workflowTaskEntity.getAppId());
                    formDataDeleteBatchDTO.setMenuId(workflowTaskEntity.getMenuId());
                    formDataDeleteBatchDTO.setSaasMark(workflowTaskEntity.getSaasMark());
                    FormDataDeleteBatchVO formDataDeleteBatchVO = workflowOperatorDataService.delete(formDataDeleteBatchDTO);
                }
            }
        } catch (Exception e) {
            log.warn("WorkflowApproveListPageOperationServiceImpl.delTask", e);
        }
        //更新任务表
        workflowTaskEntity.setDel(1);
        workflowTaskModel.update(workflowTaskEntity);
        //更新节点任务表
        workflowTaskNodeModel.deleteByTaskId(workflowTaskEntity.getId(), corpid);



        //查询钉钉待办相关
        //同一个task下的钉钉待办实例id一致
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.APPID, processTaskDelDTO.getAppId());
        param.put(ParameterConstant.FORMID, processTaskDelDTO.getFormId());
        param.put(ParameterConstant.MENUID, processTaskDelDTO.getMenuId());
        param.put(ParameterConstant.TASK_ID, processTaskDelDTO.getTaskId());
        param.put(ParameterConstant.FLOW_STATUS_IN, Arrays.asList(FlowStatusEnum.IN_APPROVAL.getType(), FlowStatusEnum.APPROVAL_PENDING.getType()));
        List<WorkflowTaskNodeEntity> taskNodeEntities = workflowTaskNodeModel.findEntities(param);
        WorkflowValidateUtil.checkQueryResult(taskNodeEntities);
        WorkflowTaskNodeEntity nodeEntity = taskNodeEntities.get(0);
        // 删除时同步删除钉钉待办实例
        if (StringUtil.isNotEmpty(nodeEntity.getDingtalkProcessInstanceId())) {
            workflowDingtalkTodoService.deleteDingtalkTodoInstance(nodeEntity.getCorpid(), nodeEntity.getDingtalkProcessInstanceId());
        }


        //操作日志
        UserVO loginUser = processTaskDelDTO.getLoginUser();
        WorkflowEntity workflowEntity = workflowModel.getByKey(workflowTaskEntity.getWorkflowId(), corpid);
        String memo =String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DEL_WORKFLOW_TASK),loginUser.getName(),nodeEntity.getTitle());
        DetailLogPojo detailLogPojo = new DetailLogPojo();
        detailLogPojo.setFromWorkflowOrApproval(workflowEntity.getName());
        detailLogPojo.setTriggerForm(paasFormEntityExt.getName());
        detailLogPojo.setWorkflowVersion(workflowEntity.getVersionName());
        mongoLogHelp.buildLog4DetailArrWithComplexDetail(Collections.singletonList(detailLogPojo),corpid,loginUser.getUserId(),loginUser.getName(), OperateModuleTypeEnum.WORKFLOW, OperateTypeEnum.APPROVAL_DEL,paasFormEntityExt.getId().toString(),nodeEntity.getTitle(),memo,processTaskDelDTO.getHttpHeader(),BasicConstant.FOUR);


        return new BaseVO();
    }
    
    
    /**
     * 获取数量
     *
     * @param workflowNodeTaskCountDTO
     */
    @Override
    public WorkflowNodeTaskCountVO count(WorkflowNodeTaskCountDTO workflowNodeTaskCountDTO) throws XbbException {
        WorkflowNodeTaskCountVO workflowNodeTaskCountVO = new WorkflowNodeTaskCountVO();
        String corpid = workflowNodeTaskCountDTO.getCorpid();
        String userId = workflowNodeTaskCountDTO.getUserId();
        try {
            // 提交给我的 待审批的
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, corpid);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            params.put("taskType", TaskTypeEnum.UNTREATED.getType());
            params.put("userId", userId);
            params.put("nodeType", NodeTypeEnum.PROCESS_NODE.getNodeType());
            Integer todo = workflowTaskNodeModel.getTaskCountLimit(params);
            workflowNodeTaskCountVO.setTodo(todo);
            
            //我已审批的 产品说不要，先备注，要了放开就行
//            params.remove("taskType");
//            params.put("taskTypeIn", Arrays.asList(
//                    TaskTypeEnum.COMMIT.getType(),
//                    TaskTypeEnum.TRANSFER.getType(),
//                    TaskTypeEnum.END.getType(),
//                    TaskTypeEnum.BACK.getType()));
//            Integer haveDone = workflowTaskNodeModel.getEntityCount(params);
            workflowNodeTaskCountVO.setHaveDone(0);
            
            // 抄送我的
            params.remove("nodeType");
            params.put("taskType", TaskTypeEnum.CC.getType());
            params.put("isRead", 0);
            Integer cc = workflowTaskNodeModel.getTaskCountLimit(params);
            workflowNodeTaskCountVO.setCc(cc);
            // 我提交的
            params.remove("userId");
            params.put("userId", workflowNodeTaskCountDTO.getUserId());
            params.put("nodeType", NodeTypeEnum.START_PROCESS_NODE.getNodeType());
            params.put("taskType", TaskTypeEnum.COMMIT.getType());
            params.put("isRead", 0);
            params.put("lastNodeId", 0);
            Integer create = workflowTaskNodeModel.getTaskCountLimit(params);
            workflowNodeTaskCountVO.setCreate(create);
            
        } catch (Exception e) {
            log.error("工作流获取卡片列表数量出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return workflowNodeTaskCountVO;
    }

    
    /**
     * 已读
     *
     * @param workflowNodeTaskReadDTO
     */
    @Override
    public BaseVO readNode(WorkflowNodeTaskReadDTO workflowNodeTaskReadDTO) throws XbbException {
        WorkflowTaskNodeEntity nodeEntity = workflowTaskNodeModel.getByKey(workflowNodeTaskReadDTO.getTaskNodeId(), workflowNodeTaskReadDTO.getCorpid());
        if (nodeEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
        }
        nodeEntity.setIsRead(1);
        workflowTaskNodeModel.readNode(nodeEntity);
        return new BaseVO();
    }
    
    /**
     * 已读所有抄送
     *
     * @param workflowNodeAllReadDTO
     */
    @Override
    public BaseVO readAllCcList(WorkflowNodeAllReadDTO workflowNodeAllReadDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        String corpid = workflowNodeAllReadDTO.getCorpid();
        String userId = workflowNodeAllReadDTO.getUserId();
        Integer nodeType = workflowNodeAllReadDTO.getNodeType();
        HashMap<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid",corpid);
        param.put("userId", userId);
        if (Objects.equals(nodeType, BasicConstant.THREE)) {
            param.put("taskType", TaskTypeEnum.CC.getType());
        }else if (Objects.equals(nodeType,BasicConstant.TWO)){
            param.put("taskType", TaskTypeEnum.COMMIT.getType());
            param.put("nodeType",NodeTypeEnum.START_PROCESS_NODE.getNodeType());
        }else {
            // 防止出现其他的问题,目前只有我提交的和抄送的,其他一律不作更新操作
            return baseVO;
        }
        param.put("readStatus",BasicConstant.ONE);
        param.put("del", 0);
        try {
            workflowTaskNodeModel.readAllCcList(param);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001,SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return baseVO;
    }
    
    /**
     * 获取审批批量打印
     *
     * @param workflowBatchPrintByProcessDTO
     */
    @Override
    public WorkflowBatchPrintByProcessVO getBatchPrintByProcess(WorkflowBatchPrintByProcessDTO workflowBatchPrintByProcessDTO) throws XbbException {
        WorkflowBatchPrintByProcessVO workflowBatchPrintByProcessVO = new WorkflowBatchPrintByProcessVO();
        // 设置appId,menuId等值
        BeanUtil.copyProperties(workflowBatchPrintByProcessDTO, workflowBatchPrintByProcessVO);
        // 打印权限
        boolean printFlag;
        if (Objects.equals(SaasMarkEnum.SAAS.getCode(), workflowBatchPrintByProcessDTO.getSaasMark())) {
            printFlag = ProPermissionHelp.hasPrintPermission(workflowBatchPrintByProcessDTO.getBusinessType(), workflowBatchPrintByProcessDTO.getLoginUser());
        } else {
            PermissionTermsPojo permissionTerms = ProPermissionHelp.getPaasFormPermission(workflowBatchPrintByProcessDTO.getLoginUser(), workflowBatchPrintByProcessDTO.getAppId(), workflowBatchPrintByProcessDTO.getMenuId());
            printFlag = Objects.equals(BasicConstant.ONE, permissionTerms.getPrint()) || workflowBatchPrintByProcessDTO.getLoginUser().isAdminOrBoss();
        }
        if(!printFlag) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100050, String.format(SystemErrorCodeEnum.API_ERROR_100050.getMsg(), "“" + workflowBatchPrintByProcessDTO.getFormName() + "”表单打印"));
        }
    
        // 获取数据
        WorkflowNodeTaskListVO workflowNodeTaskListVO = new WorkflowNodeTaskListVO();
        WorkflowNodeTaskListDTO workflowNodeTaskListDTO = new WorkflowNodeTaskListDTO();
        BeanUtil.copyProperties(workflowBatchPrintByProcessDTO, workflowNodeTaskListDTO);
        ProcessTypeEnum processTypeEnum = ProcessTypeEnum.getByValue(workflowBatchPrintByProcessDTO.getProcessType());
        if (Objects.isNull(processTypeEnum)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, "审批类型不正确");
        }
        switch (processTypeEnum) {
            case TODO:
                workflowNodeTaskListDTO.setNodeType(NodeTypeEnum.PROCESS_NODE.getNodeType());
                workflowNodeTaskListDTO.setProcessType(ProcessTypeEnum.TODO.getValue());
                workflowNodeTaskListVO = workflowApproveListPageService.todoList(workflowNodeTaskListDTO);
                break;
            case HAVE_DONE:
                workflowNodeTaskListDTO.setNodeType(NodeTypeEnum.PROCESS_NODE.getNodeType());
                workflowNodeTaskListDTO.setProcessType(ProcessTypeEnum.HAVE_DONE.getValue());
                workflowNodeTaskListVO = workflowApproveListPageService.todoList(workflowNodeTaskListDTO);
                break;
            case CREATE:
                workflowNodeTaskListDTO.setCreatorId(workflowNodeTaskListDTO.getUserId());
                workflowNodeTaskListDTO.setNodeType(NodeTypeEnum.START_PROCESS_NODE.getNodeType());
                workflowNodeTaskListVO = workflowApproveListPageService.createList(workflowNodeTaskListDTO);
                break;
            case CC:
                workflowNodeTaskListDTO.setTaskType(TaskTypeEnum.CC.getType());
                workflowNodeTaskListVO = workflowApproveListPageService.ccList(workflowNodeTaskListDTO);
                break;
            case ALL:
                workflowNodeTaskListVO = workflowApproveListPageService.allList(workflowNodeTaskListDTO);
                break;
            default:
                break;
        }
    
        List<SummaryDataVO> list = workflowNodeTaskListVO.getList();
        if (Objects.isNull(list) || list.isEmpty()) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100051, "您筛选的数据为空，无法打印！");
        }
        List<Object> resultList = new ArrayList<>();
        for (SummaryDataVO summaryDataVO : list) {
            PaasProcessNodeTaskVO processNodeTask = summaryDataVO.getProcessNodeTask();
            JSONObject object = new JSONObject();
            object.put("processTaskId", processNodeTask.getTaskId());
            object.put("processNodeTaskId", processNodeTask.getId());
        
            resultList.add(object);
        }
        workflowBatchPrintByProcessVO.setList(resultList);
    
        return workflowBatchPrintByProcessVO;
    }
    
    
    
    /**
     * 详情页
     *
     * @param workflowNodeTaskGetDTO
     */
    @Override
    public WorkflowNodeTaskGetVO detail(WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO) throws XbbException
    {
        try {
            if (XbbRefTypeEnum.workOrderV2SupportApproval().contains(workflowNodeTaskGetDTO.getBusinessType())) {
                XbbResponse<WorkflowNodeTaskGetVO> xbbResponse = workOrderV2WorkflowFeignClient.detail(workflowNodeTaskGetDTO, LocaleContextHolder.getLocale().toString());
                if (!xbbResponse.isSuccess()) {
                    throw new XbbException(xbbResponse.getCode(), xbbResponse.getMsg());
                }
                return xbbResponse.getResult();
            } else {
                return workflowApproveDetailService.detail(workflowNodeTaskGetDTO);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            log.error("工作流审批详情页出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }



    /**
     * 审批记录和抄送人列表
     *
     * @param workflowNodeTaskGetDTO
     */
    @Override
    public WorkflowNodeTaskRecordsVO records(WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO) throws XbbException {
        WorkflowNodeTaskRecordsVO workflowNodeTaskRecordsVO = new WorkflowNodeTaskRecordsVO();
        try {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 钉钉工作台特殊处理
            if (workflowNodeTaskGetDTO.getFromDingtalk()) {
                workflowOperateHelp.dealDingtalkParameter(workflowNodeTaskGetDTO);
            }
            // 不加del条件 以免离职的问题出现
            params.put(StringConstant.CORPID, workflowNodeTaskGetDTO.getCorpid());
            List<UserEntity> userList = userModel.findEntitys(params);
            if (userList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            Map<String, UserEntity> userMap = new HashMap<>(userList.size());
            userList.forEach((item) -> {
                if (Objects.equals(item.getDel(), 1)) {
                    item.setName(item.getName() + "(" + I18nMessageUtil.getMessage(I18nStringConstant.RESIGNED)+ ")");
                }
                userMap.put(item.getUserId(), item);
            });

            // 获取当前流程主任务
            WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(workflowNodeTaskGetDTO.getProcessTaskId(), workflowNodeTaskGetDTO.getCorpid());
            if (workflowTaskEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TASK_NOT_EXIST);
            }
            // 获取流程起始节点提交人信息
            UserEntity commitUserEntity = userMap.get(workflowTaskEntity.getCreatorId());

            // 获取审批记录
            params.clear();
            params.put(ParameterConstant.CORPID, workflowNodeTaskGetDTO.getCorpid());
            params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            params.put("taskId", workflowNodeTaskGetDTO.getProcessTaskId());
            params.put("orderByStr", "add_time " + SortOrder.ASC + ", id " + SortOrder.ASC);
            List<WorkflowTaskNodeEntityExt> nodeTaskList = workflowTaskNodeModel.findExtEntities(params);
            params.clear();
            params = BeanUtil.convertBean2Map(workflowNodeTaskGetDTO, true);
            // 流程模板删除后需要继续流转之前的流程 有流程流转时不允许关闭模板
            params.remove("del");
            params.put(ParameterConstant.ID, workflowTaskEntity.getWorkflowId());
            params.put(ParameterConstant.COLUMNS, "allow_view_log");
            // TODO BUG 这个模板可能不是当前流转的模板
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowTaskEntity.getWorkflowId(), workflowTaskEntity.getCorpid());
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TEMPLATE_NOT_EXIST);
            }
            //是否允许查看历史(根据当前工作流的设置来)
            Integer allowViewLog = workflowEntity.getAllowViewLog();
            //workflowHelp.getProcessNodeTaskLogList(nodeTaskList, userMap, workflowNodeTaskGetVO, workflowNodeTaskGetDTO, allowViewLog);
            WorkflowNodeTaskGetVO workflowNodeTaskGetVO = workflowHelp.getProcessNodeTaskLogList(nodeTaskList, userMap, workflowNodeTaskGetDTO);

            if (commitUserEntity != null) {
                UserVO commitUser = new UserVO();
                BeanUtil.copyProperties(commitUserEntity, commitUser);
                workflowNodeTaskGetVO.setCommitUser(commitUser);
            }
            if (Objects.equals(allowViewLog, 1)) {
                workflowNodeTaskGetVO.setApprovalHistoryLog(new ArrayList<>());
                Long dataId = workflowTaskEntity.getDataId();
                Map<String, Object> param = new HashMap<>();
                param.put(ParameterConstant.CORPID, workflowNodeTaskGetDTO.getCorpid());
                param.put("dataId", dataId);
                param.put(ParameterConstant.APPID, workflowTaskEntity.getAppId());
                param.put(ParameterConstant.MENUID, workflowTaskEntity.getMenuId());
                param.put(ParameterConstant.FORMID, workflowTaskEntity.getFormId());
                param.put(StringConstant.SAAS_MARK, workflowTaskEntity.getSaasMark());
                param.put(ParameterConstant.BUSINESS_TYPE, workflowTaskEntity.getBusinessType());
                param.put("orderByStr", "add_time " + SortOrder.ASC);
                List<WorkflowTaskEntity> taskEntities = workflowTaskModel.findEntities(param);

                //查出所有工作流，用于回显历史审批记录所属的工作流和版本信息
                Set<Long> workflowIdSet = taskEntities.stream().map(WorkflowTaskEntity::getWorkflowId).collect(Collectors.toSet());
                param.clear();
                param.put(ParameterConstant.CORPID, workflowNodeTaskGetDTO.getCorpid());
                param.put(ParameterConstant.ID_IN, workflowIdSet);
                List<WorkflowEntity> workflowEntityList = workflowModel.findEntitys(param);
                Map<Long, WorkflowEntity> workflowEntityMap = workflowEntityList.stream().collect(Collectors.toMap(WorkflowEntity::getId, v -> v));

                List<WorkflowTaskNodeEntityExt> taskNodeModelExtEntities;
                WorkflowNodeTaskGetDTO historyTaskGetDto = new WorkflowNodeTaskGetDTO();
                BeanUtil.copyProperties(workflowNodeTaskGetDTO, historyTaskGetDto);
                //key:taskId   value:taskNode
                Map<Long,List<WorkflowTaskNodeEntityExt>> historyTaskMap = new LinkedHashMap<>();
                Set<Long> taskIdList = taskEntities.stream().map(WorkflowTaskEntity::getId).collect(Collectors.toSet());
                param.clear();
                param.put(ParameterConstant.CORPID, workflowNodeTaskGetDTO.getCorpid());
                //param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                param.put("taskIdIn", taskIdList);
                param.put("orderByStr", "add_time " + SortOrder.ASC + ", id " + SortOrder.ASC);
                taskNodeModelExtEntities = workflowTaskNodeModel.findExtEntities(param);
                for (WorkflowTaskEntity taskEntity : taskEntities) {
                    Long taskId = taskEntity.getId();
                    List<WorkflowTaskNodeEntityExt> singleTaskNodeList = taskNodeModelExtEntities.stream().filter(v -> Objects.equals(v.getTaskId(), taskId)).sorted(Comparator.comparing(WorkflowTaskNodeEntityExt::getAddTime)).collect(Collectors.toList());
                    historyTaskMap.put(taskId, singleTaskNodeList);
                }
                for (Map.Entry<Long, List<WorkflowTaskNodeEntityExt>> taskNodeEntry : historyTaskMap.entrySet()) {
                    WorkflowNodeTaskGetVO workflowNodeTaskGet = new WorkflowNodeTaskGetVO();
                    Long taskId = taskNodeEntry.getKey();
                    List<WorkflowTaskNodeEntityExt> taskNodeList = taskNodeEntry.getValue();
                    Long workflowId = taskNodeList.get(0).getWorkflowId();
                    if (!Objects.equals(taskId, workflowNodeTaskGetDTO.getProcessTaskId()) && taskId < workflowNodeTaskGetDTO.getProcessTaskId()) {
                        historyTaskGetDto.setProcessNodeTaskId(taskNodeList.get(taskNodeList.size() - 1).getId());
                        historyTaskGetDto.setProcessTaskId(taskId);
                        workflowNodeTaskGet = workflowHelp.getProcessNodeTaskLogList(taskNodeList, userMap, historyTaskGetDto);
                    }
                    if(CollectionUtils.isNotEmpty(workflowNodeTaskGet.getCurrentLog())){
                        ApprovalLogPOJO approvalLogPOJO = new ApprovalLogPOJO();
                        List<Object> currentLog = workflowNodeTaskGet.getCurrentLog();
                        for (Object o : currentLog) {
                            if(o instanceof WorkflowCommentEntityExt){
                                //历史审批的评论去掉编辑和删除按钮，前端也没开放这个功能
                               ((WorkflowCommentEntityExt)o).setPermissionSet(null);
                            }
                        }
                        approvalLogPOJO.setNodeTaskList(currentLog);
                        approvalLogPOJO.setVersionName(workflowEntityMap.get(workflowId).getVersionName());
                        approvalLogPOJO.setWorkflowName(workflowEntityMap.get(workflowId).getName());
                        workflowNodeTaskGetVO.getApprovalHistoryLog().add(approvalLogPOJO);
                    }
                }
            }

            BeanUtil.copyProperties(workflowNodeTaskGetVO, workflowNodeTaskRecordsVO);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.approveListPage.impl.WorkflowApproveListPageOperationServiceImpl.records error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowNodeTaskRecordsVO;
    }
    
    /**
     * 获取流程列表中单个节点的摘要信息
     *
     * @param workflowNodeItemDTO
     */
    @Override
    public SummaryDataVO summaryItem(WorkflowNodeItemDTO workflowNodeItemDTO) throws XbbException {
        SummaryDataVO summaryDataVO = new SummaryDataVO();
        String corpid = workflowNodeItemDTO.getCorpid();
        try {
            //节点任务
            WorkflowTaskNodeEntity workflowTaskNodeEntity = workflowTaskNodeModel.getByKey(workflowNodeItemDTO.getNodeTaskId(), corpid);
            if (workflowTaskNodeEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
            }
            Long taskId = workflowTaskNodeEntity.getTaskId();
            //任务表
            WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(taskId, corpid);
            if (workflowTaskEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TASK_NOT_EXIST);
            }
            //查询主表数据
            Integer businessType = workflowTaskEntity.getBusinessType();
            Integer saasMark = workflowTaskEntity.getSaasMark();
            IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, saasMark);
            PaasFormDataEntityExt formData = paasEsModel.getByKey(workflowTaskEntity.getDataId(), corpid , indexTypeEnum, null);
            if (Objects.isNull(formData)) {

                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }

            // 表单是否存在
            PaasFormEntityExt paasFormEntityExt = new PaasFormEntityExt();
            if (Objects.equals(workflowTaskEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByKey(formData.getFormId(), corpid);
                if (workOrderFormEntity == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                BeanUtil.copyProperties(workOrderFormEntity, paasFormEntityExt);
                paasFormEntityExt.setSaasMark(SaasMarkEnum.SAAS.getCode());
                paasFormEntityExt.setBusinessType(XbbRefTypeEnum.WORK_ORDER.getCode());
            } else {
                paasFormEntityExt = paasFormModel.getByKey(formData.getFormId(), corpid);
            }
            if (paasFormEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            
            // 表单解释是否存在
            PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
            if (Objects.equals(paasFormEntityExt.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(paasFormEntityExt.getId(), corpid);
                if (workOrderExplainEntityExt == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                BeanUtil.copyProperties(workOrderExplainEntityExt, paasFormExplainEntity);
                paasFormExplainEntity.setSaasMark(SaasMarkEnum.SAAS.getCode());
                paasFormExplainEntity.setBusinessType(XbbRefTypeEnum.WORK_ORDER.getCode());
            } else {
                paasFormExplainEntity = paasFormExplainModel.getByFormId(paasFormEntityExt.getId(), corpid);
            }
            if (paasFormExplainEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            
            // 节点模板
            WorkflowNodeEntityExt entityExt = workflowNodeModel.getExtByKey(workflowTaskNodeEntity.getWorkflowNodeId(), corpid);
            if (entityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_NOT_EXIST);
            }
            
            // 用户列表
            Map<String, Object> params = BeanUtil.convertBean2Map(workflowNodeItemDTO, true);
            List<UserEntity> allUser = userModel.findEntitys(params);
            if (allUser == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            Map<String, UserEntity> userMap = allUser.stream().collect(Collectors.toMap(UserEntity::getUserId, t -> t));
    
            // 部门列表
            params.remove(ParameterConstant.COLUMNS);
            List<DepartmentEntity> departmentList = departmentModel.findEntitys(params);
            if (departmentList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DEPT_NOT_EXIST);
            }
            Map<String, DepartmentEntity> departmentMap = departmentList.stream().collect(Collectors.toMap(t->t.getId().toString(), t -> t));
            
            SummaryDataDTO summaryDataDTO = new SummaryDataDTO();
            BeanUtil.copyProperties(workflowNodeItemDTO, summaryDataDTO);
            summaryDataDTO.setTaskId(taskId);
            summaryDataDTO.setMenuId(workflowTaskNodeEntity.getMenuId());
            summaryDataDTO.setCorpid(corpid);
    
            PaasProcessDataEntity dataEntity = new PaasProcessDataEntity();
            BeanUtil.copyProperties(formData, dataEntity);
            dataEntity.setData(JSON.toJSONString(formData.getData()));
            summaryDataDTO.setPaasProcessDataEntity(dataEntity);
            
            summaryDataDTO.setPaasFormExplainEntity(paasFormExplainEntity);
            summaryDataDTO.setSummaryEntityList(entityExt.getFieldPermissionList());
            summaryDataDTO.setUserId(workflowNodeItemDTO.getUserId());
            
            PaasProcessTaskEntity entity = new PaasProcessTaskEntity();
            BeanUtil.copyProperties(workflowTaskEntity, entity);
            summaryDataDTO.setPaasProcessTaskEntity(entity);
            
            summaryDataDTO.setDepartmentMap(departmentMap);
            summaryDataDTO.setUserMap(userMap);
//            summaryDataVO = paasProcessDataService.getSummaryAndTitle(summaryDataDTO);

            PaasProcessNodeTaskVO paasProcessNodeTaskVO = new PaasProcessNodeTaskVO();
            BeanUtil.copyProperties(workflowTaskNodeEntity, paasProcessNodeTaskVO);
            paasProcessNodeTaskVO.setSaasMark(workflowTaskEntity.getSaasMark());
            paasProcessNodeTaskVO.setBusinessType(workflowTaskEntity.getBusinessType());
    
            ApprovalNode approvalNode = JsonHelperUtil.parseObject(entityExt.getConfigData(), ApprovalNode.class);
            paasProcessNodeTaskVO.setOpinionFlag(approvalNode == null ? null : approvalNode.getOpinionFlag());
            
            paasProcessNodeTaskVO.setCreatorId(workflowTaskEntity.getCreatorId());
            paasProcessNodeTaskVO.setProcessType(workflowNodeItemDTO.getProcessType());
            WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO = new WorkflowNodeTaskGetDTO();
            BeanUtil.copyProperties(workflowNodeItemDTO, workflowNodeTaskGetDTO);
            getUserName(workflowNodeTaskGetDTO, paasProcessNodeTaskVO);
            UserVO operatorUser = paasProcessNodeTaskVO.getOperatorUser();
            if (TaskTypeEnum.UNTREATED.getType().equals(paasProcessNodeTaskVO.getTaskType())
                        && workflowNodeTaskGetDTO.getUserId().equals(operatorUser.getUserId())) {
                paasProcessNodeTaskVO.setTaskTypeMemo(I18nMessageUtil.getMessage(PaasConstant.WAITING_FOR_ME_TO_APPROVE));
            } else {
                paasProcessNodeTaskVO.setTaskTypeMemo(ProcessSearchStatusTodoEnum.getStatusMemo(paasProcessNodeTaskVO.getTaskType()));
            }
            TaskTypeEnum typeEnum = TaskTypeEnum.getTaskTypeEnum(paasProcessNodeTaskVO.getTaskType());
            if (typeEnum != null) {
                paasProcessNodeTaskVO.setColor(typeEnum.getColor());
            }
            UserVO creatorUser = paasProcessNodeTaskVO.getCreatorUser();
            if (creatorUser == null) {
                summaryDataVO.setTitle("***"+ I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName());
            } else {
                summaryDataVO.setTitle(creatorUser.getName() + I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName());
            }
            summaryDataVO.setProcessNodeTask(paasProcessNodeTaskVO);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            log.error("工作流summaryItem数据库出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return summaryDataVO;
    }

    /**
     * 合计流程任务展示
     *
     * @param workflowNodeTaskCountDTO
     */
    @Override
    public WorkflowNodeTaskShowVO show(WorkflowNodeTaskCountDTO workflowNodeTaskCountDTO) throws XbbException {
        WorkflowNodeTaskShowVO workflowNodeTaskShowVO = new WorkflowNodeTaskShowVO();
        String corpid = workflowNodeTaskCountDTO.getCorpid();
        String userId = workflowNodeTaskCountDTO.getUserId();
        try {
            List<ProcessNodeTaskPojo> processNodeTaskPojoList = new ArrayList<>();
            Set<String> permSet = workflowNodeTaskCountDTO.getLoginUser().getPermSet();
            // 移动端当前模式
            MobileModeGetVO mobileModeGetVO = userConfigHelp.getMobileMode(workflowNodeTaskCountDTO);
            if (permSet.contains(ProPermissionAliasEnum.PROCESS_VIEW.getAlias())) {
                // 待审批的
                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put(StringConstant.CORPID, corpid);
                params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                params.put("taskType", TaskTypeEnum.UNTREATED.getType());
                params.put("userId", userId);
                params.put("nodeType", NodeTypeEnum.PROCESS_NODE.getNodeType());
                Integer todo = workflowTaskNodeModel.getTaskCountLimit(params);

                // 抄送我的
                params.remove("nodeType");
                params.put("taskType", TaskTypeEnum.CC.getType());
                params.put("isRead", 0);
                Integer cc = workflowTaskNodeModel.getTaskCountLimit(params);


                // 我提交的
                params.remove("userId");
                params.put("userId", workflowNodeTaskCountDTO.getUserId());
                params.put("nodeType", NodeTypeEnum.START_PROCESS_NODE.getNodeType());
                params.put("taskType", TaskTypeEnum.COMMIT.getType());
                params.put("isRead", 0);
                params.put("lastNodeId", 0);
                Integer create = workflowTaskNodeModel.getTaskCountLimit(params);

                //我已审批
                params.remove("taskType");
                params.put("taskTypeIn", Arrays.asList(
                        TaskTypeEnum.COMMIT.getType(),
                        TaskTypeEnum.TRANSFER.getType(),
                        TaskTypeEnum.END.getType(),
                        TaskTypeEnum.BACK.getType()));
                Integer haveDone = workflowTaskNodeModel.getTaskCountLimit(params);

                //根据用户模式，排序和set内容
                if(Objects.equals(mobileModeGetVO.getMode(),Constant.ONE)){
                    //专注模式
                    ProcessNodeTaskPojo todoPojo = new ProcessNodeTaskPojo();
                    todoPojo.setAlias("todo");
                    todoPojo.setName(I18nMessageUtil.getMessage(I18nStringConstant.FOR_ME_APPROVAL));
                    todoPojo.setIcon("app-icon-daishenpi");
                    todoPojo.setValue(todo);
                    processNodeTaskPojoList.add(todoPojo);

                    ProcessNodeTaskPojo haveApproved = new ProcessNodeTaskPojo();
                    haveApproved.setAlias("haveDone");
                    haveApproved.setName(I18nMessageUtil.getMessage(I18nStringConstant.I_HAVE_APPROVED));
                    haveApproved.setIcon("app-icon-tijiaowode");
                    haveApproved.setValue(haveDone);
                    processNodeTaskPojoList.add(haveApproved);

                    ProcessNodeTaskPojo creatPojo = new ProcessNodeTaskPojo();
                    creatPojo.setAlias("create");
                    creatPojo.setName(I18nMessageUtil.getMessage(I18nStringConstant.MY_SUBMITTED));
                    creatPojo.setIcon("app-icon-wotijiaode");
                    creatPojo.setValue(create);
                    processNodeTaskPojoList.add(creatPojo);

                    ProcessNodeTaskPojo ccPojo = new ProcessNodeTaskPojo();
                    ccPojo.setAlias("cc");
                    ccPojo.setName(I18nMessageUtil.getMessage(I18nStringConstant.COPY_ME));
                    ccPojo.setIcon("app-icon-chaosongwode");
                    ccPojo.setValue(cc);
                    processNodeTaskPojoList.add(ccPojo);

                }else{
                    //经典模式
                    ProcessNodeTaskPojo todoPojo = new ProcessNodeTaskPojo();
                    todoPojo.setAlias("todo");
                    todoPojo.setName(I18nMessageUtil.getMessage(I18nStringConstant.SUBMIT_TO_ME));
                    todoPojo.setIcon("app-icon-daishenpi");
                    todoPojo.setValue(todo);
                    processNodeTaskPojoList.add(todoPojo);

                    ProcessNodeTaskPojo ccPojo = new ProcessNodeTaskPojo();
                    ccPojo.setAlias("cc");
                    ccPojo.setName(I18nMessageUtil.getMessage(I18nStringConstant.COPY_ME));
                    ccPojo.setIcon("app-icon-chaosongwode");
                    ccPojo.setValue(cc);
                    processNodeTaskPojoList.add(ccPojo);

                    ProcessNodeTaskPojo creatPojo = new ProcessNodeTaskPojo();
                    creatPojo.setAlias("create");
                    creatPojo.setName(I18nMessageUtil.getMessage(I18nStringConstant.MY_SUBMITTED));
                    creatPojo.setIcon("app-icon-wotijiaode");
                    creatPojo.setValue(create);
                    processNodeTaskPojoList.add(creatPojo);

                    if (permSet.contains(ProPermissionAliasEnum.CHART_VIEW.getAlias())) {
                        ProcessNodeTaskPojo chartPojo = new ProcessNodeTaskPojo();
                        chartPojo.setAlias("chart");
                        chartPojo.setName(I18nMessageUtil.getMessage(I18nStringConstant.CHART_CENTER));
                        chartPojo.setIcon("app-icon-tubiaozhongxin");
                        chartPojo.setValue(0);
                        processNodeTaskPojoList.add(chartPojo);
                    }

                }

            }else{
                if(Objects.equals(mobileModeGetVO.getMode(),Constant.ZERO)){
                    if (permSet.contains(ProPermissionAliasEnum.CHART_VIEW.getAlias())) {
                        ProcessNodeTaskPojo chartPojo = new ProcessNodeTaskPojo();
                        chartPojo.setAlias("chart");
                        chartPojo.setName(I18nMessageUtil.getMessage(I18nStringConstant.CHART_CENTER));
                        chartPojo.setIcon("app-icon-tubiaozhongxin");
                        chartPojo.setValue(0);
                        processNodeTaskPojoList.add(chartPojo);
                    }
                }
            }

            workflowNodeTaskShowVO.setProcessNodeTaskPojoList(processNodeTaskPojoList);

        } catch (Exception e) {
            log.error("工作流show获取卡片列表出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return workflowNodeTaskShowVO;
    }

    @Override
    public WorkflowNodeTaskGetVO detailForList(WorkflowDetailForListDTO workflowDetailForListDTO) throws XbbException {


        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, workflowDetailForListDTO.getCorpid());
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(StringConstant.DATA_ID, workflowDetailForListDTO.getDataId());
        param.put(StringConstant.SAAS_MARK, workflowDetailForListDTO.getSaasMark());
        param.put(ParameterConstant.BUSINESS_TYPE, workflowDetailForListDTO.getBusinessType());
        param.put(ParameterConstant.ORDER_BY_STR, "id " + SortOrder.DESC + ", update_time " + SortOrder.DESC);

        List<WorkflowTaskEntity> workflowTaskEntities = workflowTaskModel.findEntities(param);
        if (CollectionUtils.isEmpty(workflowTaskEntities)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }

        WorkflowTaskEntity workflowTaskEntity = workflowTaskEntities.get(0);

        param.clear();
        param.put(ParameterConstant.CORPID, workflowDetailForListDTO.getCorpid());
        param.put("nodeTypeIn", Arrays.asList(NodeTypeEnum.START_PROCESS_NODE.getNodeType(), NodeTypeEnum.PROCESS_NODE.getNodeType()));
        param.put("taskTypeIn", Arrays.asList(TaskTypeEnum.UNTREATED.getType(), TaskTypeEnum.COMMIT.getType(), TaskTypeEnum.END.getType(), TaskTypeEnum.REVOKE.getType(), TaskTypeEnum.SYSTEM_COMMIT.getType()));
        param.put("orderByStr", "id " + SortOrder.DESC + ", update_time " + SortOrder.DESC);
        param.put("taskId", workflowTaskEntity.getId());
        List<WorkflowTaskNodeEntityExt> workflowTaskNodeEntityExts = workflowTaskNodeModel.getLatestNodeForList(param);
        if (CollectionUtils.isEmpty(workflowTaskNodeEntityExts)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_NOT_EXIST);
        }

        WorkflowTaskNodeEntityExt nowTaskNode = workflowTaskNodeEntityExts.get(0);
        for (WorkflowTaskNodeEntityExt workflowTaskNodeEntityExt : workflowTaskNodeEntityExts) {
            if (Objects.equals(workflowTaskNodeEntityExt.getUserId(), workflowDetailForListDTO.getUserId())) {
                nowTaskNode = workflowTaskNodeEntityExt;
                break;
            }
        }

        WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO = new WorkflowNodeTaskGetDTO();
        BeanUtil.copyProperties(workflowDetailForListDTO, workflowNodeTaskGetDTO);
        workflowNodeTaskGetDTO.setAppId(workflowTaskEntity.getAppId());
        workflowNodeTaskGetDTO.setMenuId(workflowTaskEntity.getMenuId());
        workflowNodeTaskGetDTO.setFormId(workflowTaskEntity.getFormId());
        workflowNodeTaskGetDTO.setSaasMark(workflowTaskEntity.getSaasMark());
        workflowNodeTaskGetDTO.setBusinessType(workflowTaskEntity.getBusinessType());
        workflowNodeTaskGetDTO.setProcessNodeTaskId(nowTaskNode.getId());
        workflowNodeTaskGetDTO.setProcessTaskId(workflowTaskEntity.getId());
        workflowNodeTaskGetDTO.setProcessType(ProcessTypeEnum.ALL.getValue());
        return detail(workflowNodeTaskGetDTO);
    }

    @Override
    public WorkflowNodeTaskGet4IndexVO detail4Index(WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO) throws XbbException {
        WorkflowNodeTaskGet4IndexVO workflowNodeTaskGet4IndexVO = new WorkflowNodeTaskGet4IndexVO();
        // 获取用户部门容器
        Map<String, Object> params = BeanUtil.convertBean2Map(workflowNodeTaskGetDTO, true);
        params.remove("del");
        params.put(ParameterConstant.LEAVE_MARKS, BasicConstant.ONE);
        List<UserEntity> userList = userModel.findEntitys(params);
        params.remove(ParameterConstant.LEAVE_MARKS);
        if (userList == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
        }
        Map<String, UserEntity> userMap = new HashMap<>(userList.size());
        userList.forEach((item) -> {
            if (Objects.equals(item.getDel(), 1)) {
                item.setName(item.getName() + "(" + I18nMessageUtil.getMessage(I18nStringConstant.RESIGNED)+ ")");
            }
            userMap.put(item.getUserId(), item);
        });

        workflowNodeTaskGetDTO.setUserMap(userMap);
        if (Objects.equals(workflowNodeTaskGetDTO.getNeedOperate(),BasicConstant.ONE)){
            getOperations(workflowNodeTaskGetDTO,workflowNodeTaskGet4IndexVO);
        }
        if (Objects.equals(workflowNodeTaskGetDTO.getNeedRecords(),BasicConstant.ONE)){
            getLogs(workflowNodeTaskGetDTO,workflowNodeTaskGet4IndexVO);
        }
        return workflowNodeTaskGet4IndexVO;
    }

    /**
     * 获取下一个节点的信息
     *
     * @param taskGetDTO 当前节点的信息
     * @return 下一个节点的信息
     * @throws XbbException 异常
     */
    @Override
    public ProcessNextNodeTaskGetVO nextNode(WorkflowNodeTaskGetDTO taskGetDTO) throws XbbException {
        taskGetDTO.setProcessNodeTaskId(null);
        taskGetDTO.setProcessTaskId(null);
        WorkflowNodeTaskListDTO taskListDTO = new WorkflowNodeTaskListDTO();
        taskListDTO.setCorpid(taskGetDTO.getCorpid());
        taskListDTO.setUserId(taskGetDTO.getUserId());
        taskListDTO.setLoginUser(taskGetDTO.getLoginUser());
        taskListDTO.setProcessType(ProcessTypeEnum.TODO.getValue());
        taskListDTO.setNodeType(NodeTypeEnum.PROCESS_NODE.getNodeType());
        taskListDTO.setTaskType(TaskTypeEnum.UNTREATED.getType());
        taskListDTO.setPage(BasicConstant.ONE);
        taskListDTO.setPageSize(BasicConstant.ONE);
        WorkflowNodeTaskListVO workflowNodeTaskListVO = workflowApproveListPageService.todoList(taskListDTO);
        if (Objects.isNull(workflowNodeTaskListVO) || CollectionsUtil.isEmpty(workflowNodeTaskListVO.getList())) {
            ProcessNextNodeTaskGetVO nodeTaskGetVO = new ProcessNextNodeTaskGetVO();
            nodeTaskGetVO.setExistNext(BasicConstant.ZERO);
            return nodeTaskGetVO;
        }
        PaasProcessNodeTaskVO nodeTask = workflowNodeTaskListVO.getList().get(0).getProcessNodeTask();
        WorkflowNodeTaskGetDTO nodeTaskGetDTO = new WorkflowNodeTaskGetDTO();
        BeanUtil.copyProperties(nodeTask, nodeTaskGetDTO);
        nodeTaskGetDTO.setPlatform(taskGetDTO.getPlatform());
        nodeTaskGetDTO.setProcessNodeTaskId(nodeTask.getId());
        nodeTaskGetDTO.setProcessTaskId(nodeTask.getTaskId());
        nodeTaskGetDTO.setLoginUser(taskGetDTO.getLoginUser());
        WorkflowNodeTaskGetVO nodeTaskGetVO = this.detail(nodeTaskGetDTO);
        ProcessNextNodeTaskGetVO nextNodeTaskGetVO  = new ProcessNextNodeTaskGetVO();
        BeanUtil.copyProperties(nodeTaskGetVO, nextNodeTaskGetVO);
        nextNodeTaskGetVO.setExistNext(BasicConstant.ONE);
        return nextNodeTaskGetVO;

    }

    @Override
    public ViewWholeWorkflowVO viewWholeWorkflow(ViewWholeWorkflowDTO viewWholeWorkflowDTO) throws XbbException {
        ViewWholeWorkflowVO viewWholeWorkflowVO = new ViewWholeWorkflowVO();
        String corpid = viewWholeWorkflowDTO.getCorpid();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_ACCURACY);
        params.put(ParameterConstant.CORPID, corpid);
        params.put(ParameterConstant.TASK_ID, viewWholeWorkflowDTO.getProcessTaskId());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL);
        params.put("nodeType", WorkflowNodeTypeEnum.APPROVE_NODE.getType());
        params.put(ParameterConstant.ORDER_BY_STR, "add_time desc,id desc");
        List<WorkflowTaskNodeEntity> workflowTaskNodeEntityList = workflowTaskNodeModel.findEntities(params);
        if (CollectionUtils.isEmpty(workflowTaskNodeEntityList)) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
        }
        //获取当前任务的所在节点
        WorkflowTaskNodeEntity workflowTaskNodeEntity = workflowTaskNodeEntityList.get(Constant.ZERO);
        Long workflowId = workflowTaskNodeEntity.getWorkflowId();
        WorkflowEntity workflowEntity = workflowModel.getByKey(workflowId, corpid);
        if (Objects.isNull(workflowEntity)) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
        }
        // 获取工作流节点
        List<WorkflowNodeEntity> nodeList = workflowNodeModel.getWorkflowNodeListIgnoreDel(corpid, workflowId);
        if(Objects.isNull(workflowTaskNodeEntity)){
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
        }
        WorkflowGetPojo workflowGetPojo = workflowNodeHelp.getContent(nodeList, corpid);
        List<WorkflowNodeTreePojo> workflowNodeTreeList = workflowNodeHelp.getNodeListForViewWhole(nodeList, workflowTaskNodeEntity, workflowGetPojo);

        // 建树
        WorkflowNodeTreePojo workflowNodeTreePojo = WorkflowNodeUtil.buildTree(workflowNodeTreeList, workflowTaskNodeEntity.getWorkflowNodeId());
        viewWholeWorkflowVO.setWorkflowNodeTree(workflowNodeTreePojo);
        viewWholeWorkflowVO.setWorkflow(workflowEntity);
        return viewWholeWorkflowVO;
    }


    /**
     *
     * @Description: 获取审批中修改数据的记录（只记录修改过的字段）
     * @param workflowNodeCheckUpdateRecordDTO
     * @return: com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeCheckUpdateRecordVO
     * @Author: shen.yang
     * @Date: 2022/9/23  11:04
    */
    @Override
    public WorkflowNodeCheckUpdateRecordVO checkUpdateRecord(WorkflowNodeCheckUpdateRecordDTO workflowNodeCheckUpdateRecordDTO) throws XbbException {
        WorkflowNodeCheckUpdateRecordVO workflowNodeCheckUpdateRecordVO = new WorkflowNodeCheckUpdateRecordVO();
        String corpid = workflowNodeCheckUpdateRecordDTO.getCorpid();
        Long formId = workflowNodeCheckUpdateRecordDTO.getFormId();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, corpid);
        params.put(ParameterConstant.FORMID, formId);
        params.put(ParameterConstant.TASK_ID, workflowNodeCheckUpdateRecordDTO.getProcessTaskId());
        List<WorkflowDataChangeRecordEntity> recordEntityList = workflowDataChangeRecordModel.findEntitys(params);
        if(CollectionsUtil.isEmpty(recordEntityList)){
            return workflowNodeCheckUpdateRecordVO;
        }
        List<Object> fieldRecordList = new ArrayList<>();
        // 获取表单解释
        List<FieldAttrEntity> explainList;
        if (Objects.equals(workflowNodeCheckUpdateRecordDTO.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(formId, corpid);
            if (workOrderExplainEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            explainList = JSON.parseArray(workOrderExplainEntityExt.getExplains(), FieldAttrEntity.class);
        } else {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            if (paasFormExplainEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            explainList = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        }
        //节点不可见字段剔除掉
        removeInvisibleField(corpid, workflowNodeCheckUpdateRecordDTO.getProcessTaskId(), explainList, workflowNodeCheckUpdateRecordDTO.getProcessType());
        List<String> attrList = explainList.stream().map(FieldAttrEntity::getAttr).collect(Collectors.toList());
        Map<String, FieldAttrEntity> explainMap = explainList.stream().collect(Collectors.toMap(FieldAttrEntity::getAttr, v -> v));
        //获取子表单解释，后面封装子表单的head有用
        Map<String, FieldAttrEntity> subFormFieldMap = explainList.stream().filter(v -> Objects.equals(v.getFieldType(), FieldTypeEnum.SUB_FORM.getType())).collect(Collectors.toMap(FieldAttrEntity::getAttr, v -> v));
        Map<String, List<ChangeRecordSubFormFieldBasicPojo>> subFormFieldRecordMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, List<ChangeRecordOtherFieldBasicPojo>> otherFieldRecordMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //先把所有记录的所有修改的字段按照attr放进map,后面再根据attr进行聚合
        for (WorkflowDataChangeRecordEntity workflowDataChangeRecordEntity : recordEntityList) {
            JSONArray dataArray = workflowDataChangeRecordEntity.getData();
            if(CollectionsUtil.isNotEmpty(dataArray)){
                for (Object data : dataArray) {
                    JSONObject jsonObject = (JSONObject)data;
                    String attr = jsonObject.getString(StringConstant.ATTR);
                    Boolean subFormTag = jsonObject.getBoolean(WorkflowConstant.SUBFORMTAG);
                    if(Objects.isNull(explainMap.get(attr))){
                        //设置了不可见，不处理
                        continue;
                    }
                    if(subFormTag){
                        //子表单
                        ChangeRecordSubFormFieldBasicPojo changeRecordSubFormFieldBasicPojo = JSON.toJavaObject(jsonObject, ChangeRecordSubFormFieldBasicPojo.class);
                        changeRecordSubFormFieldBasicPojo.setName(explainMap.get(attr).getAttrName());
                        changeRecordSubFormFieldBasicPojo.setAddTime(workflowDataChangeRecordEntity.getAddTime());
                        List<ChangeRecordSubFormFieldBasicPojo> orDefault = subFormFieldRecordMap.getOrDefault(attr, new ArrayList<>());
                        orDefault.add(changeRecordSubFormFieldBasicPojo);
                        subFormFieldRecordMap.put(attr, orDefault);
                    }else{
                        //普通字段
                        ChangeRecordOtherFieldBasicPojo changeRecordOtherFieldBasicPojo = JSON.toJavaObject(jsonObject, ChangeRecordOtherFieldBasicPojo.class);
                        changeRecordOtherFieldBasicPojo.setName(explainMap.get(attr).getAttrName());
                        changeRecordOtherFieldBasicPojo.setAddTime(workflowDataChangeRecordEntity.getAddTime());
                        List<ChangeRecordOtherFieldBasicPojo> orDefault = otherFieldRecordMap.getOrDefault(attr, new ArrayList<>());
                        orDefault.add(changeRecordOtherFieldBasicPojo);
                        otherFieldRecordMap.put(attr, orDefault);
                    }
                }
            }
        }

        //普通字段修改记录
        for (List<ChangeRecordOtherFieldBasicPojo> pojoList : otherFieldRecordMap.values()) {
            if(pojoList.size() > 1){
                //需要聚合
                ChangeRecordOtherFieldBasicPojo afterMergePojo = mergeOtherFieldRecord(pojoList);
                fieldRecordList.add(afterMergePojo);
            }else{
                fieldRecordList.add(pojoList.get(0));
            }
        }

        //子表单会有部门和用户字段需要填充
        params.clear();
        params.put(ParameterConstant.CORPID, workflowNodeCheckUpdateRecordDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        Map<String, UserEntity> allUserMap = userModel.findEntitys(params).stream().collect(Collectors.toMap(UserEntity::getUserId, Function.identity()));
        params.clear();
        params.put(ParameterConstant.CORPID, workflowNodeCheckUpdateRecordDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        List<DepartmentEntity> deptList = departmentModel.findEntitys(params);
        Map<Long, DepartmentEntity> allDeptMap = deptList.stream().collect(Collectors.toMap(DepartmentEntity::getId, Function.identity()));
        //子表单字段修改记录
        for (Map.Entry<String, List<ChangeRecordSubFormFieldBasicPojo>> stringListEntry : subFormFieldRecordMap.entrySet()) {
            if(Objects.isNull(subFormFieldMap.get(stringListEntry.getKey()))){
                //子表单设置了不可见，不需要处理
                continue;
            }
            List<ChangeRecordSubFormFieldBasicPojo> pojoList = stringListEntry.getValue();
            ChangeRecordSubFormFieldBasicPojo afterMergePojo = mergeSubFormFieldRecord(pojoList, subFormFieldMap.get(stringListEntry.getKey()), workflowNodeCheckUpdateRecordDTO, allUserMap, allDeptMap);
            //过滤下如果修改的字段全都是不可见的，则这条数据的修改记录看不见(只有修改的数据会出现这种情况)
            List<JSONObject> content = afterMergePojo.getContent();
            if(CollectionUtils.isNotEmpty(content)){
                Iterator<JSONObject> iterator = content.iterator();
                while(iterator.hasNext()){
                    JSONObject jsonObject = iterator.next();
                    if(Objects.equals(jsonObject.get(WorkflowConstant.OPERATETAG), OperateTypeEnum.EDIT.getCode())){
                        boolean deleteFlag = true;
                        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                            String key = entry.getKey();
                            if(!Objects.equals(key, WorkflowConstant.OPERATETAG)){
                                if(entry.getValue() instanceof ChangeRecordSubFormColumnPojo){
                                    ChangeRecordSubFormColumnPojo changeRecordSubFormColumnPojo = (ChangeRecordSubFormColumnPojo)entry.getValue();
                                    if(Objects.nonNull(changeRecordSubFormColumnPojo.getOperateTag()) && Objects.equals(changeRecordSubFormColumnPojo.getOperateTag(), OperateTypeEnum.EDIT.getCode())){
                                        deleteFlag = false;
                                        break;
                                    }
                                }
                            }
                        }
                        if(deleteFlag){
                            //说明这条修改记录能展示的字段都是没改过的，则不用展示
                            iterator.remove();
                        }
                    }
                }

            }
            //如果经过字段过滤之后，content为空了，则不记录子表单修改
            if(CollectionUtils.isNotEmpty(afterMergePojo.getContent())){
                fieldRecordList.add(afterMergePojo);
            }
        }
        //把修改记录按照解释的字段排序
        List<Object> sortedRecordList = sortRecordByExplain(fieldRecordList, attrList);
        workflowNodeCheckUpdateRecordVO.setUpdateRecordList(sortedRecordList);
        return workflowNodeCheckUpdateRecordVO;
    }

    private List<Object> sortRecordByExplain(List<Object> fieldRecordList, List<String> attrList){
        Map<String, Object> collect = fieldRecordList.stream().collect(Collectors.toMap(v ->  ((JSONObject)JSON.toJSON(v)).getString(StringConstant.ATTR), v -> v));
        List<Object> result = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(fieldRecordList)){
            for (String attr : attrList) {
                Object object = collect.get(attr);
                if(Objects.nonNull(object)){
                    result.add(object);
                }
            }
        }
        return result;
    }

    /**
     *
     * @Description: 非子表单字段，聚合审批中的修改记录
     * @return: void
     * @Author: shen.yang
     * @Date: 2022/9/22  14:34
    */
    private ChangeRecordOtherFieldBasicPojo mergeOtherFieldRecord(List<ChangeRecordOtherFieldBasicPojo> pojoList){
        pojoList.sort(Comparator.comparing(ChangeRecordOtherFieldBasicPojo::getAddTime));
        ChangeRecordOtherFieldBasicPojo firstPojo = pojoList.get(0);
        ValuePojo firstValue = firstPojo.getValue();
        ChangeRecordOtherFieldBasicPojo lastPojo = pojoList.get(pojoList.size() - 1);
        ValuePojo lastValue = lastPojo.getValue();
        //聚合规则：编辑前取第一次编辑的编辑前的值，编辑后取最后一次编辑的编辑后的值
        lastValue.setBeforeValue(firstValue.getBeforeValue());
        return lastPojo;
    }

    /**
     *
     * @Description: 根据审批节点的可见性设置，剔除不可见字段
     * @param
     * @return: void
     * @Author: shen.yang
     * @Date: 2022/10/8  11:27
    */
    private void removeInvisibleField(String corpid, Long processTaskId, List<FieldAttrEntity> explainList, String processType) throws XbbException {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, corpid);
        params.put(ParameterConstant.TASK_ID, processTaskId);
        params.put(ParameterConstant.ORDER_BY_STR, "add_time desc");
        List<WorkflowTaskNodeEntity> workflowTaskNodeEntityList = workflowTaskNodeModel.findEntities(params);
        if (CollectionUtils.isEmpty(workflowTaskNodeEntityList)) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
        }
        //获取当前任务的所在节点
        WorkflowTaskNodeEntity workflowTaskNodeEntity;
        if(Objects.equals(workflowTaskNodeEntityList.get(0).getTaskType(), TaskTypeEnum.REVOKE.getType())){
            //撤回
            workflowTaskNodeEntityList = workflowTaskNodeEntityList.stream()
                    .filter(v -> !Objects.equals(v.getNodeType(), NodeTypeEnum.START_PROCESS_NODE.getNodeType()) && Objects.equals(v.getDel(), DelEnum.DELETE.getDel()))
                    .sorted(Comparator.comparing(WorkflowTaskNodeEntity::getAddTime).reversed()).collect(Collectors.toList());
        }else{
            workflowTaskNodeEntityList = workflowTaskNodeEntityList.stream()
                    .filter(v -> !Objects.equals(v.getNodeType(), NodeTypeEnum.START_PROCESS_NODE.getNodeType()) && Objects.equals(v.getDel(), DelEnum.NORMAL.getDel()))
                    .sorted(Comparator.comparing(WorkflowTaskNodeEntity::getAddTime).reversed()).collect(Collectors.toList());
        }

        workflowTaskNodeEntity = workflowTaskNodeEntityList.get(Constant.ZERO);
        Long workflowNodeId = workflowTaskNodeEntity.getWorkflowNodeId();
        WorkflowNodeEntity workflowNodeEntity = workflowNodeModel.getByKey(workflowNodeId, corpid);
        //我提交的页面进来的，可见性要取首节点的，别的页面进来的取当前节点的
        if(Objects.equals(processType, ProcessTypeEnum.CREATE.getValue())){
            workflowNodeEntity = workflowNodeModel.getByUId(workflowNodeEntity.getWorkflowId(), corpid, WorkflowNodeTypeEnum.START_NODE.getName());
        }

        if(Objects.nonNull(workflowNodeEntity)){
            ApprovalNode approvalNode = JSON.parseObject(workflowNodeEntity.getConfigData(), ApprovalNode.class);
            Map<String, FieldPermissionEntityExt> fieldPermission = approvalNode.getFieldPermission();
            if(MapUtils.isNotEmpty(fieldPermission)){
                List<FieldAttrEntity> removeList = new ArrayList<>();
                for (FieldAttrEntity fieldAttrEntity : explainList) {
                    String attr = fieldAttrEntity.getAttr();
                    FieldPermissionEntityExt fieldPermissionEntityExt = fieldPermission.get(attr);
                    if(Objects.isNull(fieldPermissionEntityExt)){
                        //为空，则是先有的节点，后面新增了字段，这种默认是不可见不可编辑
                        removeList.add(fieldAttrEntity);
                        continue;
                    }else{
                        if(Objects.equals(fieldPermissionEntityExt.getVisible(), Constant.ZERO)){
                            removeList.add(fieldAttrEntity);
                            continue;
                        }
                    }

                    //----------子表单不可见字段处理----------
                    if(Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType())){
                        List<? extends FieldAttrEntity> items = fieldAttrEntity.getSubForm().getItems();
                        List<FieldAttrEntity> removeItems = new ArrayList<>();
                        for (FieldAttrEntity item : items) {
                            String key = attr + StringConstant.POINT + item.getAttr();
                            FieldPermissionEntityExt subFieldPermissionEntityExt = fieldPermission.get(key);
                            if(Objects.isNull(subFieldPermissionEntityExt)){
                                //为空，则是先有的节点，后面新增了字段，这种默认是不可见不可编辑
                                removeItems.add(item);
                                continue;
                            }else{
                                if(Objects.equals(subFieldPermissionEntityExt.getVisible(), Constant.ZERO)){
                                    removeItems.add(item);
                                    continue;
                                }
                            }
                        }
                        items.removeIf(removeItems :: contains);
                    }
                }
                explainList.removeIf(removeList :: contains);
            }
        }
    }

    /**
     *
     * @Description: 子表单字段，聚合审批中的修改记录
     * @return: void
     * @Author: shen.yang
     * @Date: 2022/9/22  14:34
     */
    private ChangeRecordSubFormFieldBasicPojo mergeSubFormFieldRecord(List<ChangeRecordSubFormFieldBasicPojo> pojoList, FieldAttrEntity fieldAttrEntity, WorkflowNodeCheckUpdateRecordDTO workflowNodeCheckUpdateRecordDTO, Map<String, UserEntity> allUserMap, Map<Long, DepartmentEntity> allDeptMap) throws XbbException {
        ChangeRecordSubFormFieldBasicPojo changeRecordSubFormFieldBasicPojo = new ChangeRecordSubFormFieldBasicPojo();
        ChangeRecordSubFormFieldBasicPojo pojo = pojoList.get(0);
        formatHead(changeRecordSubFormFieldBasicPojo, fieldAttrEntity);
        changeRecordSubFormFieldBasicPojo.setAttr(pojo.getAttr());
        changeRecordSubFormFieldBasicPojo.setName(pojo.getName());
        changeRecordSubFormFieldBasicPojo.setSubFormTag(pojo.getSubFormTag());

        List<ChangeRecordSubFormMidPojo> subFormDataUpdateRecordList = new ArrayList<>();
        List<? extends FieldAttrEntity> items = fieldAttrEntity.getSubForm().getItems();
        List<String> headList = items.stream().map(FieldAttrEntity :: getAttr).collect(Collectors.toList());
        Set<Long> subDataIdList = new HashSet<>();
        for (ChangeRecordSubFormFieldBasicPojo recordSubFormFieldBasicPojo : pojoList) {
            List<JSONObject> content = recordSubFormFieldBasicPojo.getContent();
            if(CollectionsUtil.isNotEmpty(content)){
                for (JSONObject jsonObject : content) {
                    ChangeRecordSubFormMidPojo changeRecordSubFormMidPojo = new ChangeRecordSubFormMidPojo();
                    Long dataId = jsonObject.getLong(StringConstant.DATA_ID);
                    changeRecordSubFormMidPojo.setDataId(dataId);
                    changeRecordSubFormMidPojo.setAddTime(recordSubFormFieldBasicPojo.getAddTime());
                    changeRecordSubFormMidPojo.setOperateTag(jsonObject.getInteger(WorkflowConstant.OPERATETAG));
                    subDataIdList.add(dataId);
                    Map<String, ChangeRecordSubFormColumnPojo> subFieldRecordMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (String subFieldAttr : headList) {
                        JSONObject subData = jsonObject.getJSONObject(subFieldAttr);
                        if(Objects.nonNull(subData)){
                            ChangeRecordSubFormColumnPojo changeRecordSubFormColumnPojo = subData.toJavaObject(ChangeRecordSubFormColumnPojo.class);
                            changeRecordSubFormColumnPojo.setAddTime(recordSubFormFieldBasicPojo.getAddTime());
                            subFieldRecordMap.put(subFieldAttr, changeRecordSubFormColumnPojo);
                        }
                    }
                    changeRecordSubFormMidPojo.setSubFieldRecordMap(subFieldRecordMap);
                    subFormDataUpdateRecordList.add(changeRecordSubFormMidPojo);
                }
            }
        }

        Map<Long, List<ChangeRecordSubFormMidPojo>> subFormMidPojoMap = subFormDataUpdateRecordList.stream().collect(Collectors.toMap(ChangeRecordSubFormMidPojo::getDataId, Collections::singletonList, (v1, v2) -> {
            List<ChangeRecordSubFormMidPojo> result = new ArrayList<>(v1);
            result.addAll(v2);
            return result;
        }));

        Integer businessType = workflowNodeCheckUpdateRecordDTO.getBusinessType();
        businessType = Objects.equals(businessType, Constant.ZERO)? XbbRefTypeEnum.PAAS.getCode() : businessType;
        //查询子表单数据,修改的行需要填充未修改内容
        List<? extends PaasFormSubDataEntity> subDataEntities = paasFormSubDataModel.getByIdList(new ArrayList<>(subDataIdList), workflowNodeCheckUpdateRecordDTO.getCorpid(), IndexTypeEnum.getSubIndexByCode(businessType));
        Map<Long, ? extends PaasFormSubDataEntity> subDataMap = subDataEntities.stream().collect(Collectors.toMap(PaasFormSubDataEntity::getId, v -> v));
        Map<String, Map<Long, ? extends PaasFormDataEntity>> subFormLinkDataMap = new HashMap<>();
        for (FieldAttrEntity item : items) {
            if(Objects.equals(item.getFieldType(), FieldTypeEnum.LINK_DATA.getType())){
                Set<Long> subLinkDataIdList = new HashSet<>();
                for (ChangeRecordSubFormFieldBasicPojo recordSubFormFieldBasicPojo : pojoList) {
                    List<JSONObject> subContent = recordSubFormFieldBasicPojo.getContent();
                    for (JSONObject jsonObject : subContent) {
                        if(Objects.equals(jsonObject.get(WorkflowConstant.OPERATETAG), OperateTypeEnum.EDIT.getCode()) && Objects.isNull(jsonObject.get(item.getAttr()))){
                            //修改的,如果没修改到关联数据字段，则要查询关联数据来填充
                            subLinkDataIdList.add(subDataMap.get(jsonObject.getLong("dataId")).getData().getLong(item.getAttr()));
                        }
                    }
                }
                LinkInfoPojo linkInfo = item.getLinkInfo();
                List<? extends PaasFormDataEntityExt> paasFormDataEntityExtList = formDataHelp.getByDataIdList(subLinkDataIdList, linkInfo.getLinkBusinessType(), linkInfo.getLinkSaasMark(), linkInfo.getLinkFormId(), workflowNodeCheckUpdateRecordDTO.getCorpid());
                if(CollectionsUtil.isNotEmpty(paasFormDataEntityExtList)){
                    Map<Long, ? extends PaasFormDataEntity> map = paasFormDataEntityExtList.stream().collect(Collectors.toMap(v -> v.getId(), v -> v));
                    subFormLinkDataMap.put(item.getAttr(), map);
                }
            }
        }

        List<JSONObject> content = new ArrayList<>();
        for (List<ChangeRecordSubFormMidPojo> value : subFormMidPojoMap.values()) {
            if(value.size() > 1){
                value.sort(Comparator.comparing(ChangeRecordSubFormMidPojo::getAddTime));
                //多次修改操作了同一条数据，需要聚合
                ChangeRecordSubFormMidPojo lastPojo = value.get(value.size() - 1);
                ChangeRecordSubFormMidPojo firstPojo = value.get(0);

                //根据多次记录，来聚合子表单每个字段的前后修改信息，整理出初始和最终的字段数据
                Map<String, List<ChangeRecordSubFormColumnPojo>> subFieldUpdateRecordMap = value.stream().map(v -> v.getSubFieldRecordMap().values()).flatMap(Collection::stream)
                        .collect(Collectors.toMap(ChangeRecordSubFormColumnPojo::getAttr, Collections::singletonList, (v1, v2) -> {
                    List<ChangeRecordSubFormColumnPojo> result = new ArrayList<>(v1);
                    result.addAll(v2);
                    return result;
                }));

                //聚合出所有涉及到的子表单字段的初始值和当前值
                Map<String, ChangeRecordSubFormColumnPojo> subFieldRecordMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (Map.Entry<String, List<ChangeRecordSubFormColumnPojo>> stringListEntry : subFieldUpdateRecordMap.entrySet()) {
                    List<ChangeRecordSubFormColumnPojo> subFieldRecordList = stringListEntry.getValue();
                    if(subFieldRecordList.size() > 1){
                        subFieldRecordList.sort(Comparator.comparing(ChangeRecordSubFormColumnPojo :: getAddTime));
                        ChangeRecordSubFormColumnPojo first = subFieldRecordList.get(0);
                        ChangeRecordSubFormColumnPojo last = subFieldRecordList.get(subFieldRecordList.size() - 1);
                        ValuePojo firstValue = first.getValue();
                        ValuePojo lastValue = last.getValue();
                        lastValue.setBeforeValue(firstValue.getBeforeValue());
                        subFieldRecordMap.put(stringListEntry.getKey(), last);
                    }else{
                        subFieldRecordMap.put(stringListEntry.getKey(), stringListEntry.getValue().get(0));
                    }

                }

                ChangeRecordSubFormMidPojo changeRecordSubFormMidPojo = null;
                //最后一次操作是删除
                if(Objects.equals(lastPojo.getOperateTag(), OperateTypeEnum.DELETE.getCode())){
                    if(Objects.equals(firstPojo.getOperateTag(), OperateTypeEnum.DELETE.getCode())){
                        //如果第一次是新增，则整体相当于没新增，不用返回此条数据记录给前端，不处理
                    }else{
                        //如果第一次不是新增，则整条数据相当于删除
                        changeRecordSubFormMidPojo = new ChangeRecordSubFormMidPojo(value.get(0).getDataId(), subFieldRecordMap, OperateTypeEnum.DELETE.getCode());
                    }
                }else{
                    if(Objects.equals(firstPojo.getOperateTag(), OperateTypeEnum.NEW.getCode())){
                        //第一次是新增，则相当于新增一条数据，要聚合最终的字段信息作为新增数据的字段信息
                        changeRecordSubFormMidPojo = new ChangeRecordSubFormMidPojo(value.get(0).getDataId(), subFieldRecordMap, OperateTypeEnum.NEW.getCode());
                    }else{
                        //第一次不是新增，聚合修改内容
                        changeRecordSubFormMidPojo = new ChangeRecordSubFormMidPojo(value.get(0).getDataId(), subFieldRecordMap, OperateTypeEnum.EDIT.getCode());
                    }
                }
                if(Objects.nonNull(changeRecordSubFormMidPojo)){
                    JSONObject obj = transferAndFillContent(changeRecordSubFormMidPojo, subDataMap, items, workflowNodeCheckUpdateRecordDTO, allUserMap, allDeptMap, subFormLinkDataMap);
                    content.add(obj);
                }
            }else{
                JSONObject obj = transferAndFillContent(value.get(0), subDataMap, items, workflowNodeCheckUpdateRecordDTO, allUserMap, allDeptMap, subFormLinkDataMap);
                content.add(obj);
            }
        }
        changeRecordSubFormFieldBasicPojo.setContent(content);
        return changeRecordSubFormFieldBasicPojo;
    }


    /**
     *
     * @Description: 前端展示需要展示全部子表单字段内容，但是修改记录的表里只存修改的字段，所以未修改字段的内容需要查出来塞进去，然后转换成前端需要的格式
     * @param changeRecordSubFormMidPojo
     * @return: com.alibaba.fastjson.JSONObject
     * @Author: shen.yang
     * @Date: 2022/9/29  17:02
    */
    private JSONObject transferAndFillContent(ChangeRecordSubFormMidPojo changeRecordSubFormMidPojo, Map<Long, ? extends PaasFormSubDataEntity> subDataMap, List<? extends FieldAttrEntity> items, WorkflowNodeCheckUpdateRecordDTO workflowNodeCheckUpdateRecordDTO, Map<String,UserEntity> allUserMap, Map<Long,DepartmentEntity> allDeptMap, Map<String, Map<Long,? extends PaasFormDataEntity>> subLinkDataMap) throws XbbException {
        JSONObject jsonObject = new JSONObject();
        Integer operateTag = changeRecordSubFormMidPojo.getOperateTag();
        jsonObject.put(WorkflowConstant.OPERATETAG, operateTag);
        Map<String, ChangeRecordSubFormColumnPojo> subFieldRecordMap = changeRecordSubFormMidPojo.getSubFieldRecordMap();
        //子表单修改，需要填充未修改字段内容
        if(Objects.equals(operateTag, OperateTypeEnum.EDIT.getCode())){
            // 通用的解析方法，主要是借用详情页的解析方法
            ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
            parseSingleRowDataDTO.setLoginUser(workflowNodeCheckUpdateRecordDTO.getLoginUser());
            parseSingleRowDataDTO.setUserId(workflowNodeCheckUpdateRecordDTO.getLoginUser().getUserId());
            parseSingleRowDataDTO.setCorpid(workflowNodeCheckUpdateRecordDTO.getCorpid());
            parseSingleRowDataDTO.setFormId(workflowNodeCheckUpdateRecordDTO.getFormId());
            parseSingleRowDataDTO.setDataId(changeRecordSubFormMidPojo.getDataId());
            PaasFormSubDataEntity paasFormSubDataEntity = subDataMap.get(changeRecordSubFormMidPojo.getDataId());
            if(Objects.nonNull(paasFormSubDataEntity)){
                JSONObject dataJson = paasFormSubDataEntity.getData();
                parseSingleRowDataDTO.setDataJsonObject(dataJson);
                Map<String,FieldAttrEntity> explainMap = items.stream().collect(Collectors.toMap(FieldAttrEntity::getAttr, v -> v));
                List<FieldAttrEntity> explainList = new ArrayList<>(items);
                parseSingleRowDataDTO.setExplainMap(explainMap);
                //下面是封装老数据的用户和部门信息
                Set<String> userSet = new HashSet<>();
                UserFieldUtil.getUserByDataInfo(dataJson, explainList, userSet);
                Set<Long> departmentIdSet = DepartmentFieldUtil.getDepartmentIdByDataInfo(dataJson, explainList);
                Map<String, UserEntity> userMap = new HashMap<>();
                Map<String, DepartmentEntity> departMap = new HashMap<>();
                if (CollectionsUtil.isNotEmpty(userSet)) {
                    userSet.forEach(v -> userMap.put(v, allUserMap.get(v)));
                }
                if (CollectionsUtil.isNotEmpty(departmentIdSet)) {
                    departmentIdSet.forEach(v -> departMap.put(v.toString(), allDeptMap.get(v)));
                }
                parseSingleRowDataDTO.setDepartmentMap(departMap);
                parseSingleRowDataDTO.setUserMap(userMap);
                parseSingleRowDataDTO.setIsProcess(true);
                ParseSingleRowDataVO parseSingleRowDataVO = formDataDetailAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                JSONObject produceOldJson = parseSingleRowDataVO.getResult();
                //子表单有关联数据的先批量查询

                for (Map.Entry<String, Object> entry : produceOldJson.entrySet()) {
                    String oldKey = entry.getKey();
                    Object oldKeyValue = entry.getValue();
                    FieldAttrEntity fieldAttrEntity = explainMap.get(oldKey);
                    if (Objects.isNull(fieldAttrEntity)) {
                        continue;
                    }
                    ChangeRecordSubFormColumnPojo changeRecordSubFormColumnPojo = subFieldRecordMap.get(oldKey);
                    if(Objects.nonNull(changeRecordSubFormColumnPojo)){
                        changeRecordSubFormColumnPojo.setOperateTag(OperateTypeEnum.EDIT.getCode());
                        continue;
                    }

                    Object newOldValue = workflowRecordLogHelp.transferSpecialFieldType(oldKeyValue, fieldAttrEntity, subLinkDataMap, workflowNodeCheckUpdateRecordDTO.getCorpid());
                    ValuePojo valuePojo = new ValuePojo(newOldValue, newOldValue);
                    changeRecordSubFormColumnPojo = new ChangeRecordSubFormColumnPojo(oldKey, fieldAttrEntity.getFieldType(), valuePojo);
                    changeRecordSubFormColumnPojo.setOperateTag(Constant.ZERO);
                    subFieldRecordMap.put(oldKey, changeRecordSubFormColumnPojo);
                }
            }
        }
        if(MapUtils.isNotEmpty(subFieldRecordMap)){
            jsonObject.putAll(subFieldRecordMap);
        }
        return jsonObject;
    }

    /**
     *
     * @Description: 封装子表单字段的表头信息
     * @param changeRecordSubFormFieldBasicPojo
     * @param fieldAttrEntity
     * @return: void
     * @Author: shen.yang
     * @Date: 2022/9/23  11:06
    */
    private void formatHead(ChangeRecordSubFormFieldBasicPojo changeRecordSubFormFieldBasicPojo, FieldAttrEntity fieldAttrEntity){
        List<ChangeRecordSubFormHeadPojo> head = new ArrayList<>();
        List<? extends FieldAttrEntity> items = fieldAttrEntity.getSubForm().getItems();
        for (FieldAttrEntity item : items) {
            head.add(new ChangeRecordSubFormHeadPojo(item.getAttr(), item.getAttrName()));
        }
        changeRecordSubFormFieldBasicPojo.setHead(head);
    }
    /**
     * 获取用户名称
     *
     * @param workflowNodeTaskGetDTO
     * @param paasProcessNodeTaskVO
     * @throws XbbException
     */
    private void getUserName(WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO, PaasProcessNodeTaskVO paasProcessNodeTaskVO) throws XbbException {
        try {
            UserGetDTO userGetDTO = new UserGetDTO();
            BeanUtil.copyProperties(workflowNodeTaskGetDTO, userGetDTO);
            List<String> userIdsList = new ArrayList<>();
            userIdsList.add(paasProcessNodeTaskVO.getCreatorId());
            userIdsList.add(paasProcessNodeTaskVO.getUserId());
            userIdsList.add(paasProcessNodeTaskVO.getTransferUserId());
            userGetDTO.setTargetUserId(userIdsList);
            UserGetVO userGetVO = userInfoHelp.getUserInfoByTargetUserId(userGetDTO);
            if (userGetVO == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            List<UserVO> userList = userGetVO.getUserList();
            Map<String, UserVO> userVOMap = new HashMap<>(userList.size());
            userList.forEach((item) -> userVOMap.put(item.getUserId(), item));
            paasProcessNodeTaskVO.setCreatorUser(userVOMap.get(paasProcessNodeTaskVO.getCreatorId()));
            paasProcessNodeTaskVO.setOperatorUser(userVOMap.get(paasProcessNodeTaskVO.getUserId()));
            if (StringUtil.isNotEmpty(paasProcessNodeTaskVO.getTransferUserId())) {
                paasProcessNodeTaskVO.setTransferUser(userVOMap.get(paasProcessNodeTaskVO.getTransferUserId()));
            }
            if (StringUtil.isNotEmpty(paasProcessNodeTaskVO.getRevokeUserId())) {
                paasProcessNodeTaskVO.setRevokeUser(userVOMap.get(paasProcessNodeTaskVO.getRevokeUserId()));
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            log.error("工作流获取用户名称失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }
    
    
    
    /**
     * 获取流程节点任务日志
     *
     */
    private void getProcessNodeTaskLogList(List<WorkflowTaskNodeEntityExt> nodeTaskList, Map<String, UserEntity> userMap,
                                           WorkflowNodeTaskGetVO workflowNodeTaskGetVO, WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO) throws XbbException {
        try {
            List<Object> historyLogList = new ArrayList<>();
            List<Object> currentLogList = new ArrayList<>();
            String corpid = workflowNodeTaskGetDTO.getCorpid();

            // 当前节点任务
            WorkflowTaskNodeEntityExt workflowTaskNodeEntityExt = null;
            for (WorkflowTaskNodeEntityExt entityExt : nodeTaskList) {
                if (Objects.equals(entityExt.getId(), workflowNodeTaskGetDTO.getProcessNodeTaskId())) {
                    workflowTaskNodeEntityExt = entityExt;
                    break;
                }
            }
            if (Objects.isNull(workflowTaskNodeEntityExt)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
            }
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowTaskNodeEntityExt.getWorkflowId(), corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TEMPLATE_NOT_EXIST);
            }
    
            Integer allowViewLog = workflowEntity.getAllowViewLog();
            WorkflowCommentListDTO commentListDTO = new WorkflowCommentListDTO();
            BeanUtil.copyProperties(workflowNodeTaskGetDTO, commentListDTO);
            commentListDTO.setRefId(workflowNodeTaskGetDTO.getProcessTaskId());
            // 审批评论类型
            commentListDTO.setBusinessType(BusinessCommentEnum.APPROVAL.getBusinessType());
            WorkflowCommentListVO commentListVO = workflowCommentService.list(commentListDTO);
            if (commentListVO == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<WorkflowCommentEntityExt> commentList = commentListVO.getList();
            Set<String> userIdSet = new HashSet<>();
            
            if (CollectionsUtil.isNotEmpty(nodeTaskList)) {
                WorkflowTaskNodeEntityExt createNodeTask = new WorkflowTaskNodeEntityExt();
                for (WorkflowTaskNodeEntityExt entityExt : nodeTaskList) {
                    if (NodeTypeEnum.START_PROCESS_NODE.getNodeType().equals(entityExt.getNodeType())) {
                        // 这里的任务是重新提交的开始节点
                        createNodeTask = entityExt;
                    }
                }
                
                List<ProcessNodeTaskLogPoJo> historyUnSubmitNodeTask = new ArrayList<>();
                List<ProcessNodeTaskLogPoJo> currentUnSubmitNodeTask = new ArrayList<>();
                List<UserEntity> ccUserList = new ArrayList<>();
                Set<Long> templateIdList = new HashSet<>();
                for (WorkflowTaskNodeEntityExt item : nodeTaskList) {
                    // 获取节点模板id
                    templateIdList.add(item.getWorkflowNodeId());
                    
                    // 过滤其他人同意的节点任务
                    if (item.getTaskType().equals(TaskTypeEnum.OTHER_COMMIT.getType())) {
                        continue;
                    }
                    // 当前节点的抄送人
                    if (item.getWorkflowNodeId().equals(workflowTaskNodeEntityExt.getWorkflowNodeId()) && item.getTaskType().equals(TaskTypeEnum.WAIT_CC.getType())  && item.getAddTime() >= createNodeTask.getUpdateTime()) {
                        // 抄送人
                        if (userMap.containsKey(item.getUserId())) {
                            ccUserList.add(userMap.get(item.getUserId()));
                        }
                        continue;
                    } else if (item.getTaskType().equals(TaskTypeEnum.WAIT_CC.getType())) {
                        continue;
                    }
                    ProcessNodeTaskLogPoJo processNodeTaskLogPoJo = getProcessNodeTaskLog(item, userMap, workflowNodeTaskGetDTO);
                   
                    if (createNodeTask.getAddTime() != null && createNodeTask.getAddTime() > item.getAddTime()) {
                        // 历史审批记录
                        if (item.getTaskType().equals(TaskTypeEnum.UNTREATED.getType())) {
                            historyUnSubmitNodeTask.add(processNodeTaskLogPoJo);
                        } else {
                            historyLogList.add(processNodeTaskLogPoJo);
                        }
                    } else {
                        // 当前审批记录
                        if (item.getTaskType().equals(TaskTypeEnum.UNTREATED.getType())) {
                            if (Objects.isNull(processNodeTaskLogPoJo.getOperatorUser())) {
                                continue;
                            }
                            if (userIdSet.contains(processNodeTaskLogPoJo.getOperatorUser().getUserId())) {
                                currentUnSubmitNodeTask.removeIf(processNodeTask -> Objects.equals(processNodeTask.getOperatorUser().getUserId(), processNodeTaskLogPoJo.getOperatorUser().getUserId()));
                            }
                            userIdSet.add(processNodeTaskLogPoJo.getOperatorUser().getUserId());
                            currentUnSubmitNodeTask.add(processNodeTaskLogPoJo);
                        } else {
                            currentLogList.add(processNodeTaskLogPoJo);
                        }
                    }
                }
                workflowNodeTaskGetVO.setCcUserList(ccUserList);
                
                // 查询所有节点
                Map<String, Object> params = new HashMap<>();
                params.put(ParameterConstant.CORPID, corpid);
                params.put("idIn", templateIdList);
                List<WorkflowNodeEntityExt> list = workflowNodeModel.list(params);
                if (Objects.isNull(list)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_NOT_EXIST);
                }
                Map<Long, WorkflowNodeEntityExt> map = list.stream().collect(Collectors.toMap(WorkflowNodeEntity::getId, t -> t));
    
                // 判断流程状态的最后一个
                if (!historyLogList.isEmpty()) {
                    // 获取最后一个节点任务
                    getUnCommitNodeTaskList(historyLogList, historyUnSubmitNodeTask);
                    // 增加节点名称
                    addTemplateNodeName(historyLogList, map);
                }
                if (!currentLogList.isEmpty()) {
                    getUnCommitNodeTaskList(currentLogList, currentUnSubmitNodeTask);
                    addTemplateNodeName(currentLogList, map);
                }
                
                if (commentList != null && !commentList.isEmpty()) {
                    for (WorkflowCommentEntityExt item : commentList) {
                        if (Objects.equals(item.getUserId(), workflowNodeTaskGetDTO.getUserId())) {
                            item.setUserName(I18nMessageUtil.getMessage(CommonConstant.ME));
                        }
                        if (createNodeTask.getAddTime() != null && createNodeTask.getAddTime() > item.getAddTime()) {
                            // 历史审批记录
                            historyLogList.add(item);
                        } else {
                            // 当前审批记录
                            currentLogList.add(item);
                        }
                    }
                }
            }
            if (!currentLogList.isEmpty()) {
                bubbleSort(currentLogList);
                sortUntreatedObject(currentLogList);
            }
            workflowNodeTaskGetVO.setCurrentLog(currentLogList);
            if (allowViewLog.equals(1)) {
                if (!historyLogList.isEmpty()) {
                    bubbleSort(historyLogList);
                    sortUntreatedObject(historyLogList);
                }
                workflowNodeTaskGetVO.setHistoryLog(historyLogList);
            } else {
                workflowNodeTaskGetVO.setHistoryLog(new ArrayList<>());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            log.error("工作流获取流程日志出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }
    
    /**
     * 强行将未处理的节点放到最后
     * @param currentLogList
     */
    private void sortUntreatedObject(List<Object> currentLogList) {
        List<Object> untreatedList = new ArrayList<>();
        Iterator<Object> iterator = currentLogList.iterator();
        while (iterator.hasNext()) {
            Object object = iterator.next();
            if (object instanceof ProcessNodeTaskLogPoJo) {
                ProcessNodeTaskLogPoJo processNodeTaskLogPoJo = (ProcessNodeTaskLogPoJo) object;
                if (Objects.equals(processNodeTaskLogPoJo.getTaskType(), TaskTypeEnum.UNTREATED.getType())) {
                    untreatedList.add(object);
                    iterator.remove();
                }
            }
        }
        currentLogList.addAll(untreatedList);
    }
    
    /**
     * 冒泡排序  按照时间排序，如果时间一样，按照id排序
     *
     * @param list
     */
    private static void bubbleSort(List<Object> list) {
        int len = list.size();
        for (int i = 0; i < len - 1; i++) {
            for (int j = 0; j < len - 1 - i; j++) {
                long addTimeLeft = 0L;
                long addTimeMid = 0L;
                long idLeft = 0L;
                long idMid = 0L;
                //long typeLeft = 0L;
                //long typeMid = 0L;
                if (list.get(j) instanceof ProcessNodeTaskLogPoJo) {
                    ProcessNodeTaskLogPoJo processNodeTaskLogPoJo = (ProcessNodeTaskLogPoJo) list.get(j);
                    addTimeLeft = processNodeTaskLogPoJo.getUpdateTime();
                    idLeft = processNodeTaskLogPoJo.getId();
                }
                if (list.get(j) instanceof WorkflowCommentEntityExt) {
                    WorkflowCommentEntityExt paasCommentEntityExt = (WorkflowCommentEntityExt) list.get(j);
                    addTimeLeft = paasCommentEntityExt.getUpdateTime();
                    idLeft = paasCommentEntityExt.getId();
                }
                if (list.get(j + 1) instanceof ProcessNodeTaskLogPoJo) {
                    ProcessNodeTaskLogPoJo processNodeTaskLogPoJo = (ProcessNodeTaskLogPoJo) list.get(j + 1);
                    addTimeMid = processNodeTaskLogPoJo.getUpdateTime();
                    idMid = processNodeTaskLogPoJo.getId();
                }
                if (list.get(j + 1) instanceof WorkflowCommentEntityExt) {
                    WorkflowCommentEntityExt paasCommentEntityExt = (WorkflowCommentEntityExt) list.get(j + 1);
                    addTimeMid = paasCommentEntityExt.getUpdateTime();
                    idMid = paasCommentEntityExt.getId();
                }
                // 相邻元素两两对比
                if (addTimeLeft == addTimeMid) {
                    //if(typeLeft == typeMid){
                    if (idLeft > idMid) {
                        elementExchange(j, list);
                    }
                    //}else if(typeLeft < typeMid){
                    //elementExchange(j, list);
                    //}
                } else if (addTimeLeft > addTimeMid) {
                    elementExchange(j, list);
                }
            }
        }
    }
    
    private static void elementExchange(int j, List<Object> list) {
        // 元素交换
        Object temp = list.get(j + 1);
        list.set(j + 1, list.get(j));
        list.set(j, temp);
    }
    
    /**
     * 增加节点名称返回
     * @param logList 历史日志和当前审批
     * @param workflowNodeEntityExtMap 查询结果
     */
    private void addTemplateNodeName(List<Object> logList, Map<Long, WorkflowNodeEntityExt> workflowNodeEntityExtMap) {
        for (Object log : logList) {
            ProcessNodeTaskLogPoJo processNodeTaskLogPoJo = (ProcessNodeTaskLogPoJo) log;
            // 判断是否是未审批
            if (TaskTypeEnum.UNTREATED.getType().equals(processNodeTaskLogPoJo.getTaskType())) {
                // 未审批从UnCommitNodeTaskList只拿第一个id
                List<ProcessNodeTaskLogPoJo> unCommitNodeTaskList = processNodeTaskLogPoJo.getUnCommitNodeTaskList();
                Long unCommiteTemplateNodeId = unCommitNodeTaskList.get(0).getTemplateNodeId();
                if (workflowNodeEntityExtMap.containsKey(unCommiteTemplateNodeId)) {
                    processNodeTaskLogPoJo.setTemplateNodeName(workflowNodeEntityExtMap.get(unCommiteTemplateNodeId).getName());
                    // 当下面这种情况时，前端渲染数据从unCommitNodeTaskList中获取，所以要往这里多放一个节点名
                    if (NodeTypeEnum.PROCESS_NODE.getNodeType().equals(processNodeTaskLogPoJo.getNodeType()) && Objects.equals(unCommitNodeTaskList.size(), 1)) {
                        unCommitNodeTaskList.get(0).setTemplateNodeName(workflowNodeEntityExtMap.get(unCommiteTemplateNodeId).getName());
                    }
                }
            } else if (workflowNodeEntityExtMap.containsKey(processNodeTaskLogPoJo.getTemplateNodeId())) {
                processNodeTaskLogPoJo.setTemplateNodeName(workflowNodeEntityExtMap.get(processNodeTaskLogPoJo.getTemplateNodeId()).getName());
            }
        }
    }
    
    /**
     * 获取没有提交的节点任务列表
     *
     * @param logList                 历史日志和当前审批
     * @param counterSignNodeTaskList 会签或或签的没有提交的任务节点
     */
    private void getUnCommitNodeTaskList(List<Object> logList, List<ProcessNodeTaskLogPoJo> counterSignNodeTaskList) {
        ProcessNodeTaskLogPoJo processNodeTaskLogPoJo = (ProcessNodeTaskLogPoJo) logList.get(logList.size() - 1);
        if (!counterSignNodeTaskList.isEmpty()
                    && processNodeTaskLogPoJo.getTemplateNodeId().equals(counterSignNodeTaskList.get(0).getTemplateNodeId())
                    && processNodeTaskLogPoJo.getNodeType().equals(TaskTypeEnum.CC.getType())) {
            processNodeTaskLogPoJo.setUnCommitNodeTaskList(counterSignNodeTaskList);
            logList.set(logList.size() - 1, processNodeTaskLogPoJo);
        } else if (!counterSignNodeTaskList.isEmpty()) {
            ProcessNodeTaskLogPoJo unCommitNodeTask = counterSignNodeTaskList.get(counterSignNodeTaskList.size()-1);
            ProcessNodeTaskLogPoJo lastNodeTask = new ProcessNodeTaskLogPoJo();
            lastNodeTask.setId(unCommitNodeTask.getId());
            lastNodeTask.setSignType(unCommitNodeTask.getSignType());
            lastNodeTask.setSignTypeDesc(SignTypeEnum.getSignTypeEnum(unCommitNodeTask.getSignType()));
            lastNodeTask.setNodeType(unCommitNodeTask.getNodeType());
            lastNodeTask.setCounterSignUnFinish(1);
            lastNodeTask.setTaskType(unCommitNodeTask.getTaskType());
            lastNodeTask.setAddTime(unCommitNodeTask.getAddTime());
            lastNodeTask.setUpdateTime(unCommitNodeTask.getUpdateTime());
            lastNodeTask.setUnCommitNodeTaskList(counterSignNodeTaskList);
            logList.add(lastNodeTask);
        }
    }
    
    /**
     * 封装流程日志对象
     *
     * @param item
     * @param userMap
     * @return
     */
    private ProcessNodeTaskLogPoJo getProcessNodeTaskLog(WorkflowTaskNodeEntityExt item, Map<String, UserEntity> userMap, WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO) throws XbbException {
        ProcessNodeTaskLogPoJo processNodeTaskLogPoJo = new ProcessNodeTaskLogPoJo();
        try {
            BeanUtil.copyProperties(item, processNodeTaskLogPoJo);
            processNodeTaskLogPoJo.setTemplateNodeId(item.getWorkflowNodeId());
            // 会签或签描述字段
            processNodeTaskLogPoJo.setSignTypeDesc(SignTypeEnum.getSignTypeEnum(item.getSignType()));
            // 审批图片
            if (StringUtil.isNotEmpty(item.getImages())) {
                processNodeTaskLogPoJo.setImages(JsonHelperUtil.parseArray(item.getImages(), String.class));
            }
            // 审批附件
            if (StringUtil.isNotEmpty(item.getAttachment())) {
                List<String> attachmentStrList = JsonHelperUtil.parseArray(item.getAttachment(), String.class);
                List<PaasAttachmentEntityExt> attachmentList = new ArrayList<>();
                attachmentStrList.forEach((attachmentItem) -> {
                    PaasAttachmentEntityExt attachment = JSONObject.parseObject(attachmentItem, PaasAttachmentEntityExt.class);
                    attachmentList.add(attachment);
                });
                processNodeTaskLogPoJo.setAttachmentList(attachmentList);
            }
            // 开始节点描述
            if (item.getNodeType().equals(NodeTypeEnum.START_PROCESS_NODE.getNodeType())) {
                processNodeTaskLogPoJo.setStartNodeDesc(I18nMessageUtil.getMessage(PaasConstant.INITIATE_AN_APPLICATION));
                if (Objects.equals(item.getTaskType(), TaskTypeEnum.REVOKE.getType())) {
                    processNodeTaskLogPoJo.setStartNodeDesc(I18nMessageUtil.getMessage(PaasConstant.REVOKE_PROCESS));
                } else if (Objects.equals(item.getTaskType(), TaskTypeEnum.AGAIN_COMMIT.getType())) {
                    processNodeTaskLogPoJo.setStartNodeDesc(TaskTypeEnum.AGAIN_COMMIT.getStatusMemo());
                }
            } else {
                processNodeTaskLogPoJo.setStartNodeDesc("");
            }
            processNodeTaskLogPoJo.setOperatorUser(userMap.get(item.getUserId()));
            // 判断负责人是否为当前登录用户
            UserEntity userEntity = processNodeTaskLogPoJo.getOperatorUser();
            processNodeTaskLogPoJo.setTaskTypeDesc(TaskTypeEnum.getStatusMemo(item.getTaskType()));
            if (userEntity != null && workflowNodeTaskGetDTO.getUserId().equals(userEntity.getUserId())) {
                processNodeTaskLogPoJo.setIsMe(1);
                processNodeTaskLogPoJo.setIsMeDesc(I18nMessageUtil.getMessage(CommonConstant.ME));
                if (item.getTaskType().equals(TaskTypeEnum.UNTREATED.getType())) {
                    processNodeTaskLogPoJo.setTaskTypeDesc(I18nMessageUtil.getMessage(PaasConstant.WAITING_FOR_ME_TO_APPROVE));
                }
            } else {
                processNodeTaskLogPoJo.setIsMe(0);
                processNodeTaskLogPoJo.setIsMeDesc("");
                if(Objects.equals(PaasConstant.SYS_USER_ID, item.getUserId())) {
                    processNodeTaskLogPoJo.setIsMeDesc(I18nMessageUtil.getMessage(CommonConstant.SYSTEM));
                    processNodeTaskLogPoJo.setOpinion(I18nMessageUtil.getMessage(I18nStringConstant.CURRENT_NODE_APPROVER_EMPTY));
                    // 系统管理员
                    UserEntity systemUser = new UserEntity();
                    systemUser.setUserId(item.getUserId());
                    systemUser.setRoleIds("|1|2|3|23|");
                    systemUser.setCorpid(item.getCorpid());
                    systemUser.setAvatar("");
                    systemUser.setName(I18nMessageUtil.getMessage(CommonConstant.SYSTEM));
                    processNodeTaskLogPoJo.setOperatorUser(systemUser);
                }
            }
            // 转交人
            if (StringUtil.isNotEmpty(item.getTransferUserId())) {
                processNodeTaskLogPoJo.setTransferUser(userMap.get(item.getTransferUserId()));
            }
            // 撤回操作人
            if (StringUtil.isNotEmpty(item.getRevokeUserId())) {
                processNodeTaskLogPoJo.setRevokeUser(userMap.get(item.getRevokeUserId()));
            }
            // 回退人
            /*if (item.getBackspaceNode() != null && item.getBackspaceNode() != 0) {
                ProcessNodeTaskGetDTO result = new ProcessNodeTaskGetDTO();
                BeanUtil.copyProperties(processNodeTaskGetDTO, result);
                Map<Long, PaasworkflowNodeEntityExt> nodeMap = getNodeMap(processNodeTaskGetDTO);
                processNodeTaskLogPoJo.setBackNodeName(nodeMap.get(item.getBackspaceNode()).getName());
            }*/
        } catch (Exception e) {
            log.error("工作流获取流程日志对象出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processNodeTaskLogPoJo;
    }




    /**
     * 获取审批操作按钮
     * @param workflowNodeTaskGetDTO
     * @return
     * @throws XbbException
     */
    private void getOperations(WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO,WorkflowNodeTaskGet4IndexVO workflowNodeTaskOperateGetVO) throws XbbException {
        String corpid = workflowNodeTaskGetDTO.getCorpid();

        // 获取用户部门容器
        Map<String, UserEntity> userMap = workflowNodeTaskGetDTO.getUserMap();

        String processType = workflowNodeTaskGetDTO.getProcessType();
        Long taskId = workflowNodeTaskGetDTO.getProcessTaskId();
        WorkflowNodeTaskGetVO workflowNodeTaskGetVO = new WorkflowNodeTaskGetVO();
        // 获取当前流程主任务
        WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(taskId, corpid);
        if (workflowTaskEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TASK_NOT_EXIST);
        }
        //查询主表数据
        List<PaasFormDataEntityExt> formDataList = formDataHelp.getByDataIdList(
                Sets.newHashSet(workflowTaskEntity.getDataId()), workflowNodeTaskGetDTO.getBusinessType(), workflowNodeTaskGetDTO.getSaasMark(), workflowNodeTaskGetDTO.getFormId(), corpid);
        if (CollectionUtils.isEmpty(formDataList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }

        // 检索流程表单数据
        PaasFormDataEntityExt formData = formDataList.get(0);
        if (formData == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        JSONObject backupData = new JSONObject();
        backupData.putAll(formData.getData());
        WorkflowTransferDataEntity workflowTransferDataEntity = workflowTransferDataModel.getByTaskId(taskId, corpid);
        WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(JSON.toJSONString(workflowTransferDataEntity.getData(), SerializerFeature.DisableCircularReferenceDetect), WorkflowTransferPOJO.class);
        formData.setData(workflowTransferPOJO.getData().getData());

        Long formDataId = formData.getId();
        workflowNodeTaskGetVO.setDataId(formDataId);

        UserEntity commitUserEntity = userMap.get(workflowTaskEntity.getCreatorId());
        if (Objects.nonNull(commitUserEntity)) {
            UserVO commitUser = new UserVO();
            BeanUtil.copyProperties(commitUserEntity, commitUser);
            workflowNodeTaskGetVO.setCommitUser(commitUser);
        } else {
            // 人员离职
            UserVO commitUser = new UserVO();
            BeanUtil.copyProperties(workflowNodeTaskGetDTO.getLoginUser(), commitUser);
            commitUser.setName("***(" + I18nMessageUtil.getMessage(I18nStringConstant.RESIGNED) + ")");
            commitUser.setUserId("0");
            workflowNodeTaskGetVO.setCommitUser(commitUser);
        }
        // 获取节点数据
        WorkflowTaskNodeEntity workflowTaskNodeEntity = workflowTaskNodeModel.getByKey(workflowNodeTaskGetDTO.getProcessNodeTaskId(), corpid);
        if (workflowTaskNodeEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
        }
        // 查询审批模板
        WorkflowEntity workflowEntity = workflowModel.getByKey(workflowTaskEntity.getWorkflowId(), corpid);
        if (workflowEntity == null ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TEMPLATE_NOT_EXIST);
        }
        // 节点模板
        WorkflowNodeEntityExt workflowNodeEntity = workflowNodeModel.getExtByKey(workflowTaskNodeEntity.getWorkflowNodeId(), corpid);
        if (workflowNodeEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_NOT_EXIST);
        }
        // 提交给我和抄送给我的用节点状态
        if (Objects.equals(ProcessTypeEnum.TODO.getValue(), processType) || Objects.equals(ProcessTypeEnum.CC.getValue(), processType)) {
            workflowNodeTaskGetVO.setFlowStatus(workflowTaskNodeEntity.getTaskType());
            workflowNodeTaskGetVO.setFlowStatusDesc(ProcessSearchStatusTodoEnum.getStatusMemo(workflowTaskNodeEntity.getTaskType()));
        } else {
            workflowNodeTaskGetVO.setFlowStatus(workflowTaskEntity.getFlowStatus());
            workflowNodeTaskGetVO.setFlowStatusDesc(FlowStatusEnum.getMemoByType(workflowTaskEntity.getFlowStatus()));
        }
        // 流程操作 未处理或者是被撤回的流程
        if (TaskTypeEnum.UNTREATED.getType().equals(workflowTaskNodeEntity.getTaskType())
                || (FlowStatusEnum.REVOKE.getType().equals(workflowTaskEntity.getFlowStatus()) && !TaskTypeEnum.END.getType().equals(workflowTaskNodeEntity.getTaskType()))
                || NodeTypeEnum.START_PROCESS_NODE.getNodeType().equals(workflowTaskNodeEntity.getNodeType())
                || TaskTypeEnum.SYSTEM_COMMIT.getType().equals(workflowTaskNodeEntity.getTaskType())) {
            workflowOperateHelp.getProcessOperator(workflowNodeEntity, workflowNodeTaskGetDTO, workflowNodeTaskGetVO, workflowEntity, workflowTaskNodeEntity, userMap, workflowTransferPOJO);
        } else {
            workflowNodeTaskGetVO.setProcessOperatePermission(new ProcessTemplateNodeVO());
        }
        ProcessNodeTaskOperatePojo operatePojo = new ProcessNodeTaskOperatePojo();
        operatePojo.setProcessTaskId(workflowNodeTaskGetDTO.getProcessTaskId());
        operatePojo.setProcessOperatePermission(workflowNodeTaskGetVO.getProcessOperatePermission());
        workflowNodeTaskOperateGetVO.setProcessNodeTaskOperatePojo(operatePojo);
    }
    /**
     * 多个审批的审批记录和抄送人列表
     *
     * @param workflowNodeTaskGetDTO
     * @return
     * @throws XbbException
     */
    public void getLogs(WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO,WorkflowNodeTaskGet4IndexVO workflowNodeTaskGet4IndexVO) throws XbbException{

        String corpid = workflowNodeTaskGetDTO.getCorpid();
        // 钉钉工作台特殊处理
        if (workflowNodeTaskGetDTO.getFromDingtalk()) {
            workflowOperateHelp.dealDingtalkParameter(workflowNodeTaskGetDTO);
        }

        Map<String, UserEntity> userMap = workflowNodeTaskGetDTO.getUserMap();

        // 获取当前流程主任务
        WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(workflowNodeTaskGetDTO.getProcessTaskId(),corpid);
        if (null == workflowTaskEntity) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TASK_NOT_EXIST);
        }
        // 查询审批模板
        WorkflowEntity workflowEntity = workflowModel.getByKey(workflowTaskEntity.getWorkflowId(), corpid);
        if (workflowEntity == null ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TEMPLATE_NOT_EXIST);
        }
        Integer allowViewLog = workflowEntity.getAllowViewLog();
        // 获取流程起始节点提交人信息
        UserEntity commitUserEntity = userMap.get(workflowTaskEntity.getCreatorId());


        // 获取审批记录
        Map<String, Object> params = BeanUtil.convertBean2Map(workflowNodeTaskGetDTO, true);
        params.put("taskId", workflowTaskEntity.getId());
        params.put("orderByStr", "update_time " + SortOrder.ASC + ", id " + SortOrder.ASC);
        params.put("corpid", corpid);
        params.put("del", 0);
        List<WorkflowTaskNodeEntityExt> nodeTaskList = workflowTaskNodeModel.findExtEntities(params);

        workflowNodeTaskGetDTO.setLoginUser(workflowNodeTaskGetDTO.getLoginUser());
        WorkflowNodeTaskGetVO workflowNodeTaskGetVO = workflowHelp.getProcessNodeTaskLogList(nodeTaskList, userMap, workflowNodeTaskGetDTO);
        if (commitUserEntity != null) {
            UserVO commitUser = new UserVO();
            BeanUtil.copyProperties(commitUserEntity, commitUser);
            workflowNodeTaskGetVO.setCommitUser(commitUser);
        }
        if (Objects.equals(allowViewLog, 1)) {
            Long dataId = workflowTaskEntity.getDataId();
            Map<String, Object> param = new HashMap<>();
            param.put(ParameterConstant.CORPID, workflowNodeTaskGetDTO.getCorpid());
            param.put("dataId", dataId);
            param.put(ParameterConstant.APPID, workflowTaskEntity.getAppId());
            param.put(ParameterConstant.MENUID, workflowTaskEntity.getMenuId());
            param.put(ParameterConstant.FORMID, workflowTaskEntity.getFormId());
            param.put(StringConstant.SAAS_MARK, workflowTaskEntity.getSaasMark());
            param.put(ParameterConstant.BUSINESS_TYPE, workflowTaskEntity.getBusinessType());
            param.put("orderByStr", "add_time " + SortOrder.DESC);
            List<WorkflowTaskEntity> taskEntities = workflowTaskModel.findEntities(param);


            List<WorkflowTaskNodeEntityExt> taskNodeModelExtEntities;
            WorkflowNodeTaskGetDTO historyTaskGetDto = new WorkflowNodeTaskGetDTO();
            BeanUtil.copyProperties(workflowNodeTaskGetDTO, historyTaskGetDto);
            for (WorkflowTaskEntity taskEntity : taskEntities) {
                if (!Objects.equals(taskEntity.getId(), workflowNodeTaskGetDTO.getProcessTaskId()) && taskEntity.getId() < workflowNodeTaskGetDTO.getProcessTaskId()) {

                    param.clear();
                    param.put(ParameterConstant.CORPID, workflowNodeTaskGetDTO.getCorpid());
                    param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                    param.put("taskId", taskEntity.getId());
                    param.put("orderByStr", "update_time " + SortOrder.ASC + ", id " + SortOrder.ASC);
                    taskNodeModelExtEntities = workflowTaskNodeModel.findExtEntities(param);
                    if (CollectionUtils.isNotEmpty(taskNodeModelExtEntities)) {
                        historyTaskGetDto.setProcessNodeTaskId(taskNodeModelExtEntities.get(taskNodeModelExtEntities.size() - 1).getId());
                        historyTaskGetDto.setProcessTaskId(taskEntity.getId());
                        WorkflowNodeTaskGetVO workflowNodeTaskGet = workflowHelp.getProcessNodeTaskLogList(taskNodeModelExtEntities, userMap, historyTaskGetDto);
                        List<Object> historyLog = workflowNodeTaskGetVO.getHistoryLog();
                        if(CollectionUtils.isNotEmpty(historyLog)){
                            workflowNodeTaskGetVO.getHistoryLog().addAll(0, workflowNodeTaskGet.getCurrentLog());
                        }else{
                            workflowNodeTaskGetVO.setHistoryLog(workflowNodeTaskGet.getCurrentLog());
                        }
                    }

                }
            }
        }

        ProcessNodeTaskRecordsPojo processNodeTaskRecordsPojo = new ProcessNodeTaskRecordsPojo();
        BeanUtil.copyProperties(workflowNodeTaskGetVO,processNodeTaskRecordsPojo );
        processNodeTaskRecordsPojo.setProcessTaskId(workflowNodeTaskGetDTO.getProcessTaskId());


        workflowNodeTaskGet4IndexVO.setProcessNodeTaskRecordsPojo(processNodeTaskRecordsPojo);

    }

    /**
     *
     * @Description: 删除没走到的条件节点，简化流程树
     * @param taskNodeList 当前任务的所有节点
     * @param currentId 当前任务节点
     * @param workflowNodeTreeList 该工作流所有节点（树节点）
     * @return: void
     * @Author: shen.yang
     * @Date: 2022/7/4  16:44
    */
    private List<WorkflowNodeTreePojo> removeNeedlessConditionNode(List<WorkflowTaskNodeEntity> taskNodeList, Long currentId, List<WorkflowNodeTreePojo> workflowNodeTreeList){
        Map<Long, WorkflowNodeTreePojo> treeNodeMap = workflowNodeTreeList.stream()
                .collect(Collectors.toMap(WorkflowNodeTreePojo::getWorkflowNodeId, v -> v));

        for (WorkflowTaskNodeEntity workflowTaskNodeEntity : taskNodeList) {
            //当前任务节点的工作流对应的节点
            Long workflowNodeId = workflowTaskNodeEntity.getWorkflowNodeId();
            //上一个节点对应的工作流节点
            Long lastNodeId = workflowTaskNodeEntity.getLastNodeId();
            WorkflowNodeTreePojo lastNodeTreePojo = treeNodeMap.get(lastNodeId);
            WorkflowNodeTreePojo workflowNodeTreePojo = new WorkflowNodeTreePojo();
            //如果上一个节点是条件块节点，需要处理条件分支
            if(Objects.equals(NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType(), lastNodeTreePojo.getType())){

            }
        }


        return (List)treeNodeMap.values();

    }

}
